Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mixin to implement an exploit's check method by invoking a scanner #11873

Merged
merged 16 commits into from
May 23, 2019
63 changes: 63 additions & 0 deletions lib/msf/core/exploit/check_scanner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# -*- coding: binary -*-

#
# This mixin implements an exploit's check method by invoking a scanner
#
# NOTE: The scanner's run_host method MUST return an Msf::Exploit::CheckCode
#

module Msf
module Exploit::Remote::CheckScanner

def initialize(info = {})
super

register_advanced_options([
OptString.new('CheckScanner', [true, 'Scanner to check with'])
])
end

# When this mixin is included, this method becomes the exploit's check method
#
# @return [Msf::Exploit::CheckCode] Whether or not the target is vulnerable
def check
# Instantiate the scanner
mod = framework.modules.create(scanner)

# Bail if we couldn't
unless mod
print_error("Could not instantiate #{scanner}")
return CheckCode::Unsupported
end

# Bail if run_host isn't defined
unless mod.respond_to?(:run_host)
print_error("#{scanner} does not define a run_host method")
return CheckCode::Unsupported
end

# Merge the exploit's datastore into the scanner's
mod.datastore.merge!(datastore)

# Use the exploit's input and output as the scanner's
mod.user_input, mod.user_output = user_input, user_output

# Use the scanner's CheckCode
checkcode = mod.run_host(rhost)

# Bail if scanner doesn't return a CheckCode
unless Exploit::CheckCode::Codes.value?(checkcode)
print_error("#{scanner} does not return a CheckCode")
return Exploit::CheckCode::Unsupported
end

# Return the CheckCode
checkcode
end

def scanner
datastore['CheckScanner']
end

end
end
1 change: 1 addition & 0 deletions lib/msf/core/exploit/mixins.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
require 'msf/core/exploit/brute'
require 'msf/core/exploit/brutetargets'
require 'msf/core/exploit/browser_autopwn'
require 'msf/core/exploit/check_scanner'

# Payload
require 'msf/core/exploit/egghunter'
Expand Down
1 change: 0 additions & 1 deletion modules/auxiliary/admin/smb/ms17_010_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ def initialize(info = {})
end

def run_host(ip)

begin
if datastore['SMBUser'].present?
print_status("Authenticating to #{ip} as user '#{splitname(datastore['SMBUser'])}'...")
Expand Down
7 changes: 7 additions & 0 deletions modules/auxiliary/scanner/smb/smb_ms17_010.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ def calculate_doublepulsar_arch(s)
end

def run_host(ip)
checkcode = Exploit::CheckCode::Unknown

begin
ipc_share = "\\\\#{ip}\\IPC$"

Expand All @@ -97,6 +99,9 @@ def run_host(ip)
end

print_good("Host is likely VULNERABLE to MS17-010! - #{os}")

checkcode = Exploit::CheckCode::Vulnerable

report_vuln(
host: ip,
name: self.name,
Expand Down Expand Up @@ -154,6 +159,8 @@ def run_host(ip)
ensure
disconnect
end

checkcode
end

def do_smb_setup_tree(ipc_share)
Expand Down
11 changes: 9 additions & 2 deletions modules/exploits/windows/smb/ms17_010_eternalblue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class MetasploitModule < Msf::Exploit::Remote
Rank = AverageRanking

include Msf::Exploit::Remote::DCERPC
include Msf::Exploit::Remote::CheckScanner

def initialize(info = {})
super(update_info(info,
Expand Down Expand Up @@ -60,7 +61,8 @@ def initialize(info = {})
'DefaultOptions' =>
{
'EXITFUNC' => 'thread',
'WfsDelay' => 5
'WfsDelay' => 5,
'CheckScanner' => 'auxiliary/scanner/smb/smb_ms17_010'
},
'Privileged' => true,
'Payload' =>
Expand Down Expand Up @@ -104,6 +106,7 @@ def initialize(info = {})
)
register_advanced_options(
[
OptBool.new('ForceExploit', [false, 'Override check result', false]),
OptString.new('ProcessName', [true, 'Process to inject payload into.', 'spoolsv.exe']),
OptInt.new('MaxExploitAttempts', [true, "The number of times to retry the exploit.", 3]),
OptInt.new('GroomAllocations', [true, "Initial number of times to groom the kernel pool.", 12]),
Expand All @@ -116,9 +119,13 @@ def initialize(info = {})
class EternalBlueError < StandardError
end

# todo: create MS17-010 mixin, and hook up auxiliary/scanner/smb/smb_ms17_010
# check is pulled in from Msf::Exploit::Remote::CheckScanner

def exploit
unless check == CheckCode::Vulnerable || datastore['ForceExploit']
fail_with(Failure::NotVulnerable, 'Set ForceExploit to override')
end

begin
for i in 1..datastore['MaxExploitAttempts']
grooms = datastore['GroomAllocations'] + datastore['GroomDelta'] * (i - 1)
Expand Down
6 changes: 5 additions & 1 deletion modules/exploits/windows/smb/ms17_010_psexec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class MetasploitModule < Msf::Exploit::Remote

include Msf::Exploit::Remote::SMB::Client::Psexec_MS17_010
include Msf::Exploit::Remote::SMB::Client::Psexec
include Msf::Exploit::Remote::CheckScanner
include Msf::Exploit::Powershell
include Msf::Exploit::EXE
include Msf::Exploit::WbemExec
Expand Down Expand Up @@ -47,7 +48,8 @@ def initialize(info = {})
'DefaultOptions' =>
{
'WfsDelay' => 10,
'EXITFUNC' => 'thread'
'EXITFUNC' => 'thread',
'CheckScanner' => 'auxiliary/scanner/smb/smb_ms17_010'
},
'References' =>
[
Expand Down Expand Up @@ -100,6 +102,8 @@ def initialize(info = {})
])
end

# check is pulled in from Msf::Exploit::Remote::CheckScanner

def exploit
begin
if datastore['SMBUser'].present?
Expand Down