mssql login : enable ntlmv2 authentification
git-svn-id: file:///home/svn/framework3/trunk@12223 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
aa72f18ec2
commit
b38a187631
|
@ -3,6 +3,7 @@ require 'msf/core/exploit/mssql_commands'
|
||||||
require 'rex/proto/ntlm/crypt'
|
require 'rex/proto/ntlm/crypt'
|
||||||
require 'rex/proto/ntlm/constants'
|
require 'rex/proto/ntlm/constants'
|
||||||
require 'rex/proto/ntlm/utils'
|
require 'rex/proto/ntlm/utils'
|
||||||
|
require 'rex/proto/ntlm/exceptions'
|
||||||
|
|
||||||
|
|
||||||
module Msf
|
module Msf
|
||||||
|
@ -17,15 +18,15 @@ module Exploit::Remote::MSSQL
|
||||||
include Exploit::Remote::MSSQL_COMMANDS
|
include Exploit::Remote::MSSQL_COMMANDS
|
||||||
include Exploit::Remote::Udp
|
include Exploit::Remote::Udp
|
||||||
include Exploit::Remote::Tcp
|
include Exploit::Remote::Tcp
|
||||||
|
include Exploit::Remote::NTLM::Client
|
||||||
|
|
||||||
#
|
#
|
||||||
# Constants
|
# Constants
|
||||||
#
|
#
|
||||||
|
|
||||||
# Ntlm
|
|
||||||
NTLM_CRYPT = Rex::Proto::NTLM::Crypt
|
NTLM_CRYPT = Rex::Proto::NTLM::Crypt
|
||||||
NTLM_CONST = Rex::Proto::NTLM::Constants
|
NTLM_CONST = Rex::Proto::NTLM::Constants
|
||||||
NTLM_UTILS = Rex::Proto::NTLM::Utils
|
NTLM_UTILS = Rex::Proto::NTLM::Utils
|
||||||
|
NTLM_XCEPT = Rex::Proto::NTLM::Exceptions
|
||||||
|
|
||||||
# Encryption
|
# Encryption
|
||||||
ENCRYPT_OFF = 0x00 #Encryption is available but off.
|
ENCRYPT_OFF = 0x00 #Encryption is available but off.
|
||||||
|
@ -67,15 +68,16 @@ module Exploit::Remote::MSSQL
|
||||||
Opt::RPORT(1433),
|
Opt::RPORT(1433),
|
||||||
OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']),
|
OptString.new('USERNAME', [ false, 'The username to authenticate as', 'sa']),
|
||||||
OptString.new('PASSWORD', [ false, 'The password for the specified username', '']),
|
OptString.new('PASSWORD', [ false, 'The password for the specified username', '']),
|
||||||
|
|
||||||
OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentification', false]),
|
OptBool.new('USE_WINDOWS_AUTHENT', [ true, 'Use windows authentification', false]),
|
||||||
], Msf::Exploit::Remote::MSSQL)
|
], Msf::Exploit::Remote::MSSQL)
|
||||||
register_advanced_options(
|
register_advanced_options(
|
||||||
[
|
[
|
||||||
OptPath.new('HEX2BINARY', [ false, "The path to the hex2binary script on the disk",
|
OptPath.new('HEX2BINARY', [ false, "The path to the hex2binary script on the disk",
|
||||||
File.join(Msf::Config.install_root, "data", "exploits", "mssql", "h2b")
|
File.join(Msf::Config.install_root, "data", "exploits", "mssql", "h2b")
|
||||||
])
|
]),
|
||||||
|
OptString.new('DOMAIN', [ true, 'The domain to use for windows authentification', 'WORKSTATION'])
|
||||||
], Msf::Exploit::Remote::MSSQL)
|
], Msf::Exploit::Remote::MSSQL)
|
||||||
|
|
||||||
register_autofilter_ports([ 1433, 1434, 1435, 14330, 2533, 9152, 2638 ])
|
register_autofilter_ports([ 1433, 1434, 1435, 14330, 2533, 9152, 2638 ])
|
||||||
register_autofilter_services(%W{ ms-sql-s ms-sql2000 sybase })
|
register_autofilter_services(%W{ ms-sql-s ms-sql2000 sybase })
|
||||||
end
|
end
|
||||||
|
@ -416,8 +418,21 @@ module Exploit::Remote::MSSQL
|
||||||
aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) #application and library name
|
aname = Rex::Text.to_unicode( Rex::Text.rand_text_alpha(rand(8)+1) ) #application and library name
|
||||||
sname = Rex::Text.to_unicode( rhost )
|
sname = Rex::Text.to_unicode( rhost )
|
||||||
dname = Rex::Text.to_unicode( db )
|
dname = Rex::Text.to_unicode( db )
|
||||||
|
|
||||||
|
ntlm_options = {
|
||||||
|
:signing => false,
|
||||||
|
:usentlm2_session => datastore['NTLM::UseNTLM2_session'],
|
||||||
|
:use_ntlmv2 => datastore['NTLM::UseNTLMv2'],
|
||||||
|
:send_lm => datastore['NTLM::SendLM'],
|
||||||
|
:send_ntlm => 'NTLM::SendNTLM'
|
||||||
|
}
|
||||||
|
|
||||||
|
ntlmssp_flags = NTLM_UTILS.make_ntlm_flags(ntlm_options)
|
||||||
|
workstation_name = Rex::Text.rand_text_alpha(rand(8)+1)
|
||||||
|
domain_name = datastore['DOMAIN']
|
||||||
|
|
||||||
# use a default value for now
|
# use a default value for now
|
||||||
ntlmsspblob = NTLM_UTILS::make_ntlmssp_blob_init('WORKGROUP','WORKSTATION', 0xa2080205)
|
ntlmsspblob = NTLM_UTILS::make_ntlmssp_blob_init(domain_name, workstation_name, ntlmssp_flags)
|
||||||
|
|
||||||
idx = pkt.size + 50 # lengths below
|
idx = pkt.size + 50 # lengths below
|
||||||
|
|
||||||
|
@ -470,38 +485,38 @@ module Exploit::Remote::MSSQL
|
||||||
# is set to STATUS_NORMAL and not STATUS_END_OF_MESSAGE, then internally it waits for the ntlm_authentification
|
# 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)
|
resp = mssql_send_recv(pkt,15, false)
|
||||||
|
|
||||||
# Extract the NTLM challenge key the lazy way
|
# Get default data
|
||||||
cidx = resp.index("NTLMSSP\x00\x02\x00\x00\x00")
|
begin
|
||||||
|
blob_data = NTLM_UTILS.parse_ntlm_type_2_blob(resp)
|
||||||
|
# a domain.length < 3 will hit this
|
||||||
|
rescue NTLM_XCEPT::NTLMMissingChallenge
|
||||||
|
info = {:errors => []}
|
||||||
|
mssql_parse_reply(resp, info)
|
||||||
|
mssql_print_reply(info)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
challenge_key = blob_data[:challenge_key]
|
||||||
|
server_ntlmssp_flags = blob_data[:server_ntlmssp_flags] #else should raise an error
|
||||||
|
#netbios name
|
||||||
|
default_name = blob_data[:default_name] || ''
|
||||||
|
#netbios domain
|
||||||
|
default_domain = blob_data[:default_domain] || ''
|
||||||
|
#dns name
|
||||||
|
dns_host_name = blob_data[:dns_host_name] || ''
|
||||||
|
#dns domain
|
||||||
|
dns_domain_name = blob_data[:dns_domain_name] || ''
|
||||||
|
#Client time
|
||||||
|
chall_MsvAvTimestamp = blob_data[:chall_MsvAvTimestamp] || ''
|
||||||
|
|
||||||
#add exception and ...
|
spnopt = {:use_spn => datastore['NTLM::SendNTLM'], :name => self.rhost}
|
||||||
#if (cidx == -1)
|
|
||||||
# raise XCEPT::NTLM2MissingChallenge
|
|
||||||
#end
|
|
||||||
#for the moment :
|
|
||||||
raise Error,"No challenge" if not cidx
|
|
||||||
|
|
||||||
resp.slice!(0,cidx)
|
resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge = NTLM_UTILS.create_lm_ntlm_responses(user, pass, challenge_key,
|
||||||
|
domain_name, default_name, default_domain,
|
||||||
|
dns_host_name, dns_domain_name, chall_MsvAvTimestamp,
|
||||||
|
spnopt, ntlm_options)
|
||||||
|
|
||||||
challenge_key = resp[24, 8]
|
ntlmssp = NTLM_UTILS.make_ntlmssp_blob_auth(domain_name, workstation_name, user, resp_lm, resp_ntlm, '', ntlmssp_flags)
|
||||||
|
|
||||||
#!!!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
|
# Create an SSPIMessage
|
||||||
idx = 0
|
idx = 0
|
||||||
pkt = ''
|
pkt = ''
|
||||||
|
|
|
@ -2,6 +2,13 @@ module Rex
|
||||||
module Proto
|
module Proto
|
||||||
module NTLM
|
module NTLM
|
||||||
module Exceptions
|
module Exceptions
|
||||||
|
|
||||||
|
class NTLMMissingChallenge < ::RuntimeError
|
||||||
|
def to_s
|
||||||
|
"Unable to complete, no challenge key found"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
require 'rex/proto/ntlm/constants'
|
require 'rex/proto/ntlm/constants'
|
||||||
require 'rex/proto/ntlm/crypt'
|
require 'rex/proto/ntlm/crypt'
|
||||||
|
require 'rex/proto/ntlm/exceptions'
|
||||||
|
|
||||||
module Rex
|
module Rex
|
||||||
module Proto
|
module Proto
|
||||||
|
@ -8,6 +9,7 @@ class Utils
|
||||||
|
|
||||||
CONST = Rex::Proto::NTLM::Constants
|
CONST = Rex::Proto::NTLM::Constants
|
||||||
CRYPT = Rex::Proto::NTLM::Crypt
|
CRYPT = Rex::Proto::NTLM::Crypt
|
||||||
|
XCEPT = Rex::Proto::NTLM::Exceptions
|
||||||
|
|
||||||
#duplicate from lib/rex/proto/smb/utils cause we only need this fonction from Rex::Proto::SMB::Utils
|
#duplicate from lib/rex/proto/smb/utils cause we only need this fonction from Rex::Proto::SMB::Utils
|
||||||
# Convert a unix timestamp to a 64-bit signed server time
|
# Convert a unix timestamp to a 64-bit signed server time
|
||||||
|
@ -376,7 +378,7 @@ class Utils
|
||||||
cidx = blob.index("NTLMSSP\x00\x02\x00\x00\x00")
|
cidx = blob.index("NTLMSSP\x00\x02\x00\x00\x00")
|
||||||
|
|
||||||
if not cidx
|
if not cidx
|
||||||
raise XCEPT::NTLM2MissingChallenge
|
raise XCEPT::NTLMMissingChallenge
|
||||||
end
|
end
|
||||||
|
|
||||||
data[:challenge_key] = blob[cidx + 24, 8]
|
data[:challenge_key] = blob[cidx + 24, 8]
|
||||||
|
|
Loading…
Reference in New Issue