Land #5958, fix VulnAttempt creation

MSP-13233

Still needs styleguide cleanup.
bug/bundler_fix 4.11.4-2015091002
James Lee 2015-09-09 18:31:40 -05:00
commit ec3aecbc9d
No known key found for this signature in database
GPG Key ID: 2D6094C7CEA0A321
5 changed files with 93 additions and 86 deletions

View File

@ -154,6 +154,90 @@ module Exploit
nil
end
def setup_fail_detail_from_exception e
# Build a user-friendly error message
msg = "#{e}"
unless e.class == Msf::Exploit::Failed
msg = "#{e.class} #{e}"
end
self.error = e
# Record the detailed reason
self.fail_detail ||= e.to_s
msg
end
#
# Handle the exception
#
def handle_exception e
msg = setup_fail_detail_from_exception e
case e
when Msf::Exploit::Complete
# Nothing to show in this case
return
when Msf::Exploit::Failed
self.print_error("Exploit aborted due to failure: #{self.fail_reason}: #{msg}")
# The caller should have already set self.fail_reason
if self.fail_reason == Msf::Exploit::Failure::None
self.fail_reason = Msf::Exploit::Failure::Unknown
end
when Rex::ConnectionError
self.fail_reason = Msf::Exploit::Failure::Unreachable
self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}")
elog("Exploit failed (#{self.refname}): #{msg}", 'core', LEV_0)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
when Timeout::Error
self.fail_reason = Msf::Exploit::Failure::TimeoutExpired
self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}")
elog("Exploit failed (#{self.refname}): #{msg}", 'core', LEV_0)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
else
# Compare as a string since not all error classes may be loaded
case msg
when /access.denied|Login Failed/i # Covers SMB as well as some generic errors
self.fail_reason = Msf::Exploit::Failure::NoAccess
when /connection reset/i
self.fail_reason = Msf::Exploit::Failure::Disconnected
when /connection timed out|SSL_connect|unreachable|connection was refused/i
self.fail_reason = Msf::Exploit::Failure::Unreachable
when /unable.*target/i
self.fail_reason = Msf::Exploit::Failure::NoTarget
when /execution expired/i
self.fail_reason = Msf::Exploit::Failure::TimeoutExpired
when /(doesn.t|not).*vulnerable|may.*patched/i
self.fail_reason = Msf::Exploit::Failure::NotVulnerable
end
# The caller should have already set self.fail_reason
if self.fail_reason == Msf::Exploit::Failure::None
self.fail_reason = Msf::Exploit::Failure::Unknown
end
if self.fail_reason == Msf::Exploit::Failure::Unknown
self.print_error("Exploit failed: #{msg}")
else
self.print_error("Exploit failed [#{self.fail_reason}]: #{msg}")
end
elog("Exploit failed (#{self.refname}): #{msg}", 'core', LEV_0)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
end
# Record the error to various places
self.framework.events.on_module_error(self, msg)
# Report the failure (and attempt) in the database
self.report_failure
end
#
# Calls the class method.
#

View File

@ -119,6 +119,7 @@ module Msf::DBManager::ExploitAttempt
username = opts[:username]
mname = opts[:module]
if vuln.nil?
ref_names = mrefs.map { |ref|
if ref.respond_to?(:ctx_id) and ref.respond_to?(:ctx_val)

View File

@ -46,7 +46,8 @@ module Msf::DBManager::Vuln
def find_vuln_by_refs(refs, host, service=nil)
ref_ids = refs.find_all { |ref| ref.name.starts_with? 'CVE-'}
host.vulns.includes(:refs).where(service_id: service.try(:id), refs: { id: ref_ids}).first
relation = host.vulns.includes(:refs)
relation.where(service_id: service.try(:id), refs: { id: ref_ids}).first || relation.where(refs: { id: ref_ids}).first
end
def get_vuln(wspace, host, service, name, data='')

View File

@ -1260,7 +1260,6 @@ class Exploit < Msf::Module
end
def report_failure
return unless framework.db and framework.db.active
info = {
@ -1293,6 +1292,7 @@ class Exploit < Msf::Module
)
end
framework.db.report_exploit_failure(info)
end

View File

@ -113,7 +113,6 @@ class ExploitDriver
# - Cleans up the handler
#
def run
# First thing's first -- validate the state. Make sure all requirement
# parameters are set, including those that are derived from the
# datastore.
@ -164,6 +163,7 @@ class ExploitDriver
# nothing should be able to modify their datastore or other
# settings until after they're done.
ctx = [ exploit, payload ]
job_run_proc(ctx)
job_cleanup_proc(ctx)
end
@ -187,18 +187,15 @@ class ExploitDriver
protected
#
# Job run proc, sets up the exploit and kicks it off.
#
def job_run_proc(ctx)
# Default session wait time..
delay = payload.wfs_delay + exploit.wfs_delay
delay = nil if exploit.passive?
begin
exploit, payload = ctx
# Default session wait time..
delay = payload.wfs_delay + exploit.wfs_delay
delay = nil if exploit.passive?
# Set the exploit up the bomb
exploit.setup
@ -208,88 +205,12 @@ protected
# Launch the exploit
exploit.exploit
rescue ::Exception => e
if [::RuntimeError, ::Interrupt].include?(e.class)
# Wait for session, but don't wait long.
delay = 0.01
end
# Build a user-friendly error message
msg = "#{e}"
unless e.class == Msf::Exploit::Failed
msg = "#{e.class} #{e}"
end
exploit.error = e
# Record the detailed reason
exploit.fail_detail ||= e.to_s
case e
when Msf::Exploit::Complete
# Nothing to show in this case
return
when Msf::Exploit::Failed
exploit.print_error("Exploit aborted due to failure: #{exploit.fail_reason}: #{msg}")
# The caller should have already set exploit.fail_reason
if exploit.fail_reason == Msf::Exploit::Failure::None
exploit.fail_reason = Msf::Exploit::Failure::Unknown
end
when Rex::ConnectionError
exploit.fail_reason = Msf::Exploit::Failure::Unreachable
exploit.print_error("Exploit failed [#{exploit.fail_reason}]: #{msg}")
elog("Exploit failed (#{exploit.refname}): #{msg}", 'core', LEV_0)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
when Timeout::Error
exploit.fail_reason = Msf::Exploit::Failure::TimeoutExpired
exploit.print_error("Exploit failed [#{exploit.fail_reason}]: #{msg}")
elog("Exploit failed (#{exploit.refname}): #{msg}", 'core', LEV_0)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
else
# Compare as a string since not all error classes may be loaded
case msg
when /access.denied|Login Failed/i # Covers SMB as well as some generic errors
exploit.fail_reason = Msf::Exploit::Failure::NoAccess
when /connection reset/i
exploit.fail_reason = Msf::Exploit::Failure::Disconnected
when /connection timed out|SSL_connect|unreachable|connection was refused/i
exploit.fail_reason = Msf::Exploit::Failure::Unreachable
when /unable.*target/i
exploit.fail_reason = Msf::Exploit::Failure::NoTarget
when /execution expired/i
exploit.fail_reason = Msf::Exploit::Failure::TimeoutExpired
when /(doesn.t|not).*vulnerable|may.*patched/i
exploit.fail_reason = Msf::Exploit::Failure::NotVulnerable
end
# The caller should have already set exploit.fail_reason
if exploit.fail_reason == Msf::Exploit::Failure::None
exploit.fail_reason = Msf::Exploit::Failure::Unknown
end
if exploit.fail_reason == Msf::Exploit::Failure::Unknown
exploit.print_error("Exploit failed: #{msg}")
else
exploit.print_error("Exploit failed [#{exploit.fail_reason}]: #{msg}")
end
elog("Exploit failed (#{exploit.refname}): #{msg}", 'core', LEV_0)
dlog("Call stack:\n#{e.backtrace.join("\n")}", 'core', LEV_3)
end
# Record the error to various places
exploit.framework.events.on_module_error(exploit, msg)
# Report the failure (and attempt) in the database
exploit.report_failure
exploit.handle_exception e
end
# Wait the payload to acquire a session if this isn't a passive-style