mssql login : enable windows authentification and add an encrypion check through tds prelogin mechanism
see issue #402 for some comment on the implementation and the todo's git-svn-id: file:///home/svn/framework3/trunk@12154 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
25ca59b56f
commit
08df8179cc
|
@ -1,5 +1,9 @@
|
|||
require 'msf/core'
|
||||
require 'msf/core/exploit/mssql_commands'
|
||||
require 'rex/proto/ntlm/crypt'
|
||||
require 'rex/proto/ntlm/constants'
|
||||
require 'rex/proto/ntlm/utils'
|
||||
|
||||
|
||||
module Msf
|
||||
|
||||
|
@ -14,6 +18,42 @@ module Exploit::Remote::MSSQL
|
|||
include Exploit::Remote::Udp
|
||||
include Exploit::Remote::Tcp
|
||||
|
||||
#
|
||||
# Constants
|
||||
#
|
||||
|
||||
# Ntlm
|
||||
NTLM_CRYPT = Rex::Proto::NTLM::Crypt
|
||||
NTLM_CONST = Rex::Proto::NTLM::Constants
|
||||
NTLM_UTILS = Rex::Proto::NTLM::Utils
|
||||
|
||||
# Encryption
|
||||
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.
|
||||
|
||||
# Paquet Type
|
||||
TYPE_SQL_BATCH = 1 # (Client) SQL command
|
||||
TYPE_PRE_TDS7_LOGIN = 2 # (Client) Pre-login with version < 7 (unused)
|
||||
TYPE_RPC = 3 # (Client) RPC
|
||||
TYPE_TABLE_RESPONSE = 4 # (Server) Pre-Login Response ,Login Response, Row Data, Return Status, Return Parameters,
|
||||
# Request Completion, Error and Info Messages, Attention Acknowledgement
|
||||
TYPE_ATTENTION_SIGNAL = 6 # (Client) Attention
|
||||
TYPE_BULK_LOAD = 7 # (Client) SQL Command with binary data
|
||||
TYPE_TRANSACTION_MANAGER_REQUEST = 14 # (Client) Transaction request manager
|
||||
TYPE_TDS7_LOGIN = 16 # (Client) Login
|
||||
TYPE_SSPI_MESSAGE = 17 # (Client) Login
|
||||
TYPE_PRE_LOGIN_MESSAGE = 18 # (Client) pre-login with version > 7
|
||||
|
||||
# Status
|
||||
STATUS_NORMAL = 0x00
|
||||
STATUS_END_OF_MESSAGE = 0x01
|
||||
STATUS_IGNORE_EVENT = 0x02
|
||||
STATUS_RESETCONNECTION = 0x08 # TDS 7.1+
|
||||
STATUS_RESETCONNECTIONSKIPTRAN = 0x10 # TDS 7.3+
|
||||
|
||||
|
||||
#
|
||||
# Creates an instance of a MSSQL exploit module.
|
||||
#
|
||||
|
@ -27,6 +67,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(
|
||||
[
|
||||
|
@ -198,7 +239,7 @@ module Exploit::Remote::MSSQL
|
|||
#
|
||||
# Send and receive using TDS
|
||||
#
|
||||
def mssql_send_recv(req, timeout=15)
|
||||
def mssql_send_recv(req, timeout=15, check_status = true)
|
||||
sock.put(req)
|
||||
|
||||
# Read the 8 byte header to get the length and status
|
||||
|
@ -215,7 +256,7 @@ module Exploit::Remote::MSSQL
|
|||
end
|
||||
|
||||
# Is this the last buffer?
|
||||
if(head[1,1] == "\x01")
|
||||
if(head[1,1] == "\x01" or not check_status )
|
||||
done = true
|
||||
end
|
||||
|
||||
|
@ -241,6 +282,92 @@ 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 = [
|
||||
TYPE_PRE_LOGIN_MESSAGE, #type
|
||||
STATUS_END_OF_MESSAGE, #status
|
||||
0x0000, #length
|
||||
0x0000, # SPID
|
||||
0x00, # PacketID
|
||||
0x00 #Window
|
||||
]
|
||||
|
||||
version = [0x55010008,0x0000].pack("Vv")
|
||||
encryption = ENCRYPT_NOT_SUP # off
|
||||
instoptdata = "MSSQLServer\0"
|
||||
|
||||
threadid = "\0\0" + Rex::Text.rand_text(2)
|
||||
|
||||
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 ENCRYPT_NOT_SUP and hope for the best
|
||||
encryption_mode = ENCRYPT_NOT_SUP
|
||||
end
|
||||
|
||||
|
||||
|
||||
if encryption_mode != ENCRYPT_NOT_SUP 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,85 +378,235 @@ module Exploit::Remote::MSSQL
|
|||
disconnect if self.sock
|
||||
connect
|
||||
|
||||
pkt = ""
|
||||
idx = 0
|
||||
# Send a prelogin packet and check that encryption is not enabled
|
||||
if mssql_prelogin() != ENCRYPT_NOT_SUP
|
||||
print_error("Encryption is not supported")
|
||||
return false
|
||||
end
|
||||
|
||||
if datastore['USE_WINDOWS_AUTHENT']
|
||||
|
||||
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')
|
||||
idx = 0
|
||||
pkt = ''
|
||||
pkt_hdr = ''
|
||||
pkt_hdr = [
|
||||
TYPE_TDS7_LOGIN, #type
|
||||
STATUS_END_OF_MESSAGE, #status
|
||||
0x0000, #length
|
||||
0x0000, # SPID
|
||||
0x01, # PacketID (unused upon specification
|
||||
# but ms network monitor stil prefer 1 to decode correctly, wireshark don't care)
|
||||
0x00 #Window
|
||||
]
|
||||
|
||||
pkt << [
|
||||
0x00000000, # Size
|
||||
0x71000001, # TDS Version
|
||||
0x00000000, # Dummy 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')
|
||||
|
||||
cname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) )
|
||||
aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) #application and library name
|
||||
sname = Rex::Text.to_unicode( rhost )
|
||||
dname = Rex::Text.to_unicode( db )
|
||||
# use a default value for now
|
||||
ntlmsspblob = NTLM_UTILS::make_ntlmssp_blob_init('WORKGROUP','WORKSTATION', 0xa2080205)
|
||||
|
||||
idx = pkt.size + 50 # lengths below
|
||||
|
||||
pkt << [idx, cname.length / 2].pack('vv')
|
||||
idx += cname.length
|
||||
|
||||
pkt << [0, 0].pack('vv') # User length offset must be 0
|
||||
pkt << [0, 0].pack('vv') # Password length offset must be 0
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << [idx, sname.length / 2].pack('vv')
|
||||
idx += sname.length
|
||||
|
||||
pkt << [0, 0].pack('vv') # unused
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << [idx, 0].pack('vv') # locales
|
||||
|
||||
pkt << [idx, 0].pack('vv') #db
|
||||
|
||||
# ClientID (should be mac address)
|
||||
pkt << Rex::Text.rand_text(6)
|
||||
|
||||
# NTLMSSP
|
||||
pkt << [idx, ntlmsspblob.length].pack('vv')
|
||||
idx += ntlmsspblob.length
|
||||
|
||||
pkt << [idx, 0].pack('vv') # AtchDBFile
|
||||
|
||||
pkt << cname
|
||||
pkt << aname
|
||||
pkt << sname
|
||||
pkt << aname
|
||||
pkt << ntlmsspblob
|
||||
|
||||
# Total packet length
|
||||
pkt[0,4] = [pkt.length].pack('V')
|
||||
|
||||
pkt_hdr[2] = pkt.length + 8
|
||||
|
||||
pkt = pkt_hdr.pack("CCnnCC") + pkt
|
||||
|
||||
# Rem : One have to set check_status to false here because sql server sp0 (and maybe above)
|
||||
# has a strange behavior that differs from the specifications
|
||||
# upon receiving the ntlm_negociate request it send an ntlm_challenge but the status flag of the tds packet header
|
||||
# is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification
|
||||
resp = mssql_send_recv(pkt,15, false)
|
||||
|
||||
# Extract the NTLM challenge key the lazy way
|
||||
cidx = resp.index("NTLMSSP\x00\x02\x00\x00\x00")
|
||||
|
||||
#add exception and ...
|
||||
#if (cidx == -1)
|
||||
# raise XCEPT::NTLM2MissingChallenge
|
||||
#end
|
||||
#for the moment :
|
||||
raise Error,"No challenge" if not cidx
|
||||
|
||||
resp.slice!(0,cidx)
|
||||
|
||||
challenge_key = resp[24, 8]
|
||||
|
||||
#!!!TEMPORARY SOLUTION !!! (copy/paste from smb/client.rb)!!!
|
||||
# Until ntlm proto will have a wrapper in lib/msf and will be integrated in smb and here
|
||||
# we will use ntlm2_session response only and hope for the best ... (no ntlmv2 , no signing for now ...)
|
||||
|
||||
|
||||
client_challenge = Rex::Text.rand_text(8)
|
||||
argntlm = {
|
||||
:ntlm_hash => NTLM_CRYPT::ntlm_hash(pass),
|
||||
:challenge => challenge_key
|
||||
}
|
||||
|
||||
optntlm = { :client_challenge => client_challenge}
|
||||
resp_ntlm = NTLM_CRYPT::ntlm2_session(argntlm,optntlm).join[24,24]
|
||||
# Generate the fake LANMAN hash
|
||||
resp_lm = client_challenge + ("\x00" * 16)
|
||||
|
||||
ntlmssp = NTLM_UTILS.make_ntlmssp_blob_auth('WORKGROUP','WORKSTATION', user, resp_lm, resp_ntlm,
|
||||
'', 0xa2080205)
|
||||
# Create an SSPIMessage
|
||||
idx = 0
|
||||
pkt = ''
|
||||
pkt_hdr = ''
|
||||
pkt_hdr = [
|
||||
TYPE_SSPI_MESSAGE, #type
|
||||
STATUS_END_OF_MESSAGE, #status
|
||||
0x0000, #length
|
||||
0x0000, # SPID
|
||||
0x01, # PacketID
|
||||
0x00 #Window
|
||||
]
|
||||
|
||||
pkt_hdr[2] = ntlmssp.length + 8
|
||||
|
||||
pkt = pkt_hdr.pack("CCnnCC") + ntlmssp
|
||||
|
||||
resp = mssql_send_recv(pkt)
|
||||
|
||||
|
||||
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 )
|
||||
#SQL Server Authentification
|
||||
else
|
||||
idx = 0
|
||||
pkt = ''
|
||||
pkt << [
|
||||
0x00000000, # Dummy size
|
||||
|
||||
idx = pkt.size + 50 # lengths below
|
||||
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, cname.length / 2].pack('vv')
|
||||
idx += cname.length
|
||||
|
||||
pkt << [idx, uname.length / 2].pack('vv')
|
||||
idx += uname.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 )
|
||||
|
||||
pkt << [idx, pname.length / 2].pack('vv')
|
||||
idx += pname.length
|
||||
idx = pkt.size + 50 # lengths below
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
pkt << [idx, cname.length / 2].pack('vv')
|
||||
idx += cname.length
|
||||
|
||||
pkt << [idx, sname.length / 2].pack('vv')
|
||||
idx += sname.length
|
||||
pkt << [idx, uname.length / 2].pack('vv')
|
||||
idx += uname.length
|
||||
|
||||
pkt << [0, 0].pack('vv')
|
||||
pkt << [idx, pname.length / 2].pack('vv')
|
||||
idx += pname.length
|
||||
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << [idx, 0].pack('vv')
|
||||
pkt << [idx, sname.length / 2].pack('vv')
|
||||
idx += sname.length
|
||||
|
||||
pkt << [idx, dname.length / 2].pack('vv')
|
||||
idx += dname.length
|
||||
pkt << [0, 0].pack('vv')
|
||||
|
||||
# The total length has to be embedded twice more here
|
||||
pkt << [
|
||||
0,
|
||||
0,
|
||||
0x12345678,
|
||||
0x12345678
|
||||
].pack('vVVV')
|
||||
pkt << [idx, aname.length / 2].pack('vv')
|
||||
idx += aname.length
|
||||
|
||||
pkt << cname
|
||||
pkt << uname
|
||||
pkt << pname
|
||||
pkt << aname
|
||||
pkt << sname
|
||||
pkt << aname
|
||||
pkt << dname
|
||||
pkt << [idx, 0].pack('vv')
|
||||
|
||||
# Total packet length
|
||||
pkt[0,4] = [pkt.length].pack('V')
|
||||
pkt << [idx, dname.length / 2].pack('vv')
|
||||
idx += dname.length
|
||||
|
||||
# Embedded packet lengths
|
||||
pkt[pkt.index([0x12345678].pack('V')), 8] = [pkt.length].pack('V') * 2
|
||||
# The total length has to be embedded twice more here
|
||||
pkt << [
|
||||
0,
|
||||
0,
|
||||
0x12345678,
|
||||
0x12345678
|
||||
].pack('vVVV')
|
||||
|
||||
# Packet header and total length including header
|
||||
pkt = "\x10\x01" + [pkt.length + 8].pack('n') + [0].pack('n') + [1].pack('C') + "\x00" + pkt
|
||||
pkt << cname
|
||||
pkt << uname
|
||||
pkt << pname
|
||||
pkt << aname
|
||||
pkt << sname
|
||||
pkt << aname
|
||||
pkt << dname
|
||||
|
||||
resp = mssql_send_recv(pkt)
|
||||
# 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)
|
||||
|
||||
end
|
||||
|
||||
info = {:errors => []}
|
||||
info = mssql_parse_reply(resp,info)
|
||||
|
|
|
@ -116,6 +116,26 @@ class Utils
|
|||
return blob
|
||||
end
|
||||
|
||||
# BLOB without GSS usefull for ntlmssp type 1 message
|
||||
def self.make_ntlmssp_blob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
|
||||
blob = "NTLMSSP\x00" +
|
||||
[1, flags].pack('VV') +
|
||||
|
||||
[
|
||||
domain.length, #length
|
||||
domain.length, #max length
|
||||
32
|
||||
].pack('vvV') +
|
||||
|
||||
[
|
||||
name.length, #length
|
||||
name.length, #max length
|
||||
domain.length + 32
|
||||
].pack('vvV') +
|
||||
|
||||
domain + name
|
||||
return blob
|
||||
end
|
||||
|
||||
# GSS BLOB usefull for ntlmssp type 1 message
|
||||
def self.make_ntlmssp_secblob_init(domain = 'WORKGROUP', name = 'WORKSTATION', flags=0x80201)
|
||||
|
@ -135,22 +155,7 @@ class Utils
|
|||
) +
|
||||
"\xa2" + self.asn1encode(
|
||||
"\x04" + self.asn1encode(
|
||||
"NTLMSSP\x00" +
|
||||
[1, flags].pack('VV') +
|
||||
|
||||
[
|
||||
domain.length, #length
|
||||
domain.length, #max length
|
||||
32
|
||||
].pack('vvV') +
|
||||
|
||||
[
|
||||
name.length, #length
|
||||
name.length, #max length
|
||||
domain.length + 32
|
||||
].pack('vvV') +
|
||||
|
||||
domain + name
|
||||
make_ntlmssp_blob_init(domain, name, flags)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -161,33 +166,6 @@ class Utils
|
|||
end
|
||||
|
||||
|
||||
# GSS BLOB usefull for ntlmssp type 2 message
|
||||
def self.make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
|
||||
|
||||
blob =
|
||||
"\xa1" + self.asn1encode(
|
||||
"\x30" + self.asn1encode(
|
||||
"\xa0" + self.asn1encode(
|
||||
"\x0a" + self.asn1encode(
|
||||
"\x01"
|
||||
)
|
||||
) +
|
||||
"\xa1" + self.asn1encode(
|
||||
"\x06" + self.asn1encode(
|
||||
"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
|
||||
)
|
||||
) +
|
||||
"\xa2" + self.asn1encode(
|
||||
"\x04" + self.asn1encode(
|
||||
make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
return blob
|
||||
end
|
||||
|
||||
# BLOB without GSS usefull for ntlm type 2 message
|
||||
def self.make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
|
||||
|
||||
|
@ -219,10 +197,35 @@ class Utils
|
|||
return blob
|
||||
end
|
||||
|
||||
# GSS BLOB usefull for ntlmssp type 2 message
|
||||
def self.make_ntlmssp_secblob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
|
||||
|
||||
blob =
|
||||
"\xa1" + self.asn1encode(
|
||||
"\x30" + self.asn1encode(
|
||||
"\xa0" + self.asn1encode(
|
||||
"\x0a" + self.asn1encode(
|
||||
"\x01"
|
||||
)
|
||||
) +
|
||||
"\xa1" + self.asn1encode(
|
||||
"\x06" + self.asn1encode(
|
||||
"\x2b\x06\x01\x04\x01\x82\x37\x02\x02\x0a"
|
||||
)
|
||||
) +
|
||||
"\xa2" + self.asn1encode(
|
||||
"\x04" + self.asn1encode(
|
||||
make_ntlmssp_blob_chall(win_domain, win_name, dns_domain, dns_name, chall, flags)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
# GSS BLOB Usefull for ntlmssp type 3 message
|
||||
def self.make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
|
||||
return blob
|
||||
end
|
||||
|
||||
# BLOB without GSS Usefull for ntlmssp type 3 message
|
||||
def self.make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
|
||||
lm ||= "\x00" * 24
|
||||
ntlm ||= "\x00" * 24
|
||||
|
||||
|
@ -232,59 +235,67 @@ class Utils
|
|||
session = enc_session_key
|
||||
|
||||
ptr = 64
|
||||
|
||||
blob = "NTLMSSP\x00" +
|
||||
[ 3 ].pack('V') +
|
||||
|
||||
[ # Lan Manager Response
|
||||
lm.length,
|
||||
lm.length,
|
||||
(ptr)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # NTLM Manager Response
|
||||
ntlm.length,
|
||||
ntlm.length,
|
||||
(ptr += lm.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # Domain Name
|
||||
domain_uni.length,
|
||||
domain_uni.length,
|
||||
(ptr += ntlm.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # Username
|
||||
user_uni.length,
|
||||
user_uni.length,
|
||||
(ptr += domain_uni.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # Hostname
|
||||
name_uni.length,
|
||||
name_uni.length,
|
||||
(ptr += user_uni.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # Session Key (none)
|
||||
session.length,
|
||||
session.length,
|
||||
(ptr += name_uni.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ flags ].pack('V') +
|
||||
|
||||
lm +
|
||||
ntlm +
|
||||
domain_uni +
|
||||
user_uni +
|
||||
name_uni +
|
||||
session + "\x00"
|
||||
return blob
|
||||
|
||||
end
|
||||
|
||||
# GSS BLOB Usefull for ntlmssp type 3 message
|
||||
def self.make_ntlmssp_secblob_auth(domain, name, user, lm, ntlm, enc_session_key, flags = 0x080201)
|
||||
|
||||
blob =
|
||||
"\xa1" + self.asn1encode(
|
||||
"\x30" + self.asn1encode(
|
||||
"\xa2" + self.asn1encode(
|
||||
"\x04" + self.asn1encode(
|
||||
|
||||
"NTLMSSP\x00" +
|
||||
[ 3 ].pack('V') +
|
||||
|
||||
[ # Lan Manager Response
|
||||
lm.length,
|
||||
lm.length,
|
||||
(ptr)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # NTLM Manager Response
|
||||
ntlm.length,
|
||||
ntlm.length,
|
||||
(ptr += lm.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # Domain Name
|
||||
domain_uni.length,
|
||||
domain_uni.length,
|
||||
(ptr += ntlm.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # Username
|
||||
user_uni.length,
|
||||
user_uni.length,
|
||||
(ptr += domain_uni.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # Hostname
|
||||
name_uni.length,
|
||||
name_uni.length,
|
||||
(ptr += user_uni.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ # Session Key (none)
|
||||
session.length,
|
||||
session.length,
|
||||
(ptr += name_uni.length)
|
||||
].pack('vvV') +
|
||||
|
||||
[ flags ].pack('V') +
|
||||
|
||||
lm +
|
||||
ntlm +
|
||||
domain_uni +
|
||||
user_uni +
|
||||
name_uni +
|
||||
session + "\x00"
|
||||
make_ntlmssp_blob_auth(domain, name, user, lm, ntlm, enc_session_key, flags )
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue