mssql login : enable ntlmv2 authentification

git-svn-id: file:///home/svn/framework3/trunk@12223 4d416f70-5f16-0410-b530-b9f4589650da
unstable
amaloteaux 2011-04-03 17:02:23 +00:00
parent aa72f18ec2
commit b38a187631
3 changed files with 65 additions and 41 deletions

View File

@ -3,6 +3,7 @@ require 'msf/core/exploit/mssql_commands'
require 'rex/proto/ntlm/crypt'
require 'rex/proto/ntlm/constants'
require 'rex/proto/ntlm/utils'
require 'rex/proto/ntlm/exceptions'
module Msf
@ -17,15 +18,15 @@ module Exploit::Remote::MSSQL
include Exploit::Remote::MSSQL_COMMANDS
include Exploit::Remote::Udp
include Exploit::Remote::Tcp
include Exploit::Remote::NTLM::Client
#
# Constants
#
# Ntlm
NTLM_CRYPT = Rex::Proto::NTLM::Crypt
NTLM_CONST = Rex::Proto::NTLM::Constants
NTLM_UTILS = Rex::Proto::NTLM::Utils
NTLM_XCEPT = Rex::Proto::NTLM::Exceptions
# Encryption
ENCRYPT_OFF = 0x00 #Encryption is available but off.
@ -67,15 +68,16 @@ 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(
[
OptPath.new('HEX2BINARY', [ false, "The path to the hex2binary script on the disk",
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)
register_autofilter_ports([ 1433, 1434, 1435, 14330, 2533, 9152, 2638 ])
register_autofilter_services(%W{ ms-sql-s ms-sql2000 sybase })
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
sname = Rex::Text.to_unicode( rhost )
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
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
@ -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
resp = mssql_send_recv(pkt,15, false)
# Extract the NTLM challenge key the lazy way
cidx = resp.index("NTLMSSP\x00\x02\x00\x00\x00")
# Get default data
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 ...
#if (cidx == -1)
# raise XCEPT::NTLM2MissingChallenge
#end
#for the moment :
raise Error,"No challenge" if not cidx
spnopt = {:use_spn => datastore['NTLM::SendNTLM'], :name => self.rhost}
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
idx = 0
pkt = ''

View File

@ -2,6 +2,13 @@ module Rex
module Proto
module NTLM
module Exceptions
class NTLMMissingChallenge < ::RuntimeError
def to_s
"Unable to complete, no challenge key found"
end
end
end
end
end

View File

@ -1,5 +1,6 @@
require 'rex/proto/ntlm/constants'
require 'rex/proto/ntlm/crypt'
require 'rex/proto/ntlm/exceptions'
module Rex
module Proto
@ -8,6 +9,7 @@ class Utils
CONST = Rex::Proto::NTLM::Constants
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
# 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")
if not cidx
raise XCEPT::NTLM2MissingChallenge
raise XCEPT::NTLMMissingChallenge
end
data[:challenge_key] = blob[cidx + 24, 8]