2013-09-05 01:39:02 +00:00
##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# web site for more information on licensing and terms of use.
# http://metasploit.com/
##
require 'msf/core'
class Metasploit3 < Msf :: Auxiliary
include Msf :: Exploit :: Remote :: HttpClient
include Msf :: Auxiliary :: Scanner
include Msf :: Auxiliary :: Report
def initialize
super (
'Name' = > 'Host Information Enumeration via NTLM Authentication' ,
'Description' = > %q{
This module makes requests to resources on the target server in
an attempt to find resources which permit NTLM authentication . For
resources which permit NTLM authentication a blank NTLM type 1 message
is sent to enumerate a a type 2 message from the target server . The type
2 message is then parsed for information such as the Active Directory
domain and NetBIOS name .
} ,
'Author' = > 'Brandon Knight' ,
'License' = > MSF_LICENSE
)
register_options (
[
OptPath . new ( 'TARGETURIS' , [ false , " Path to list of URIs to request " , File . join ( Msf :: Config . install_root , " data " , " wordlists " , " http_owa_common.txt " ) ] )
] , self . class )
end
def peer
return " #{ rhost } : #{ rport } "
end
def run_host ( ip )
File . open ( datastore [ 'TARGETURIS' ] , 'rb' ) . each_line do | line |
2013-09-05 14:06:11 +00:00
test_uri = line . chomp
tpath = normalize_uri ( test_uri )
result = check_url ( tpath )
2013-09-05 01:39:02 +00:00
if result
2013-09-05 14:06:11 +00:00
print_good ( " Enumerated info on #{ peer } #{ tpath } - (name: #{ result [ :nbname ] } ) (domain: #{ result [ :nbdomain ] } ) (domain_fqdn: #{ result [ :dnsdomain ] } ) (server_fqdn: #{ result [ :dnsserver ] } ) " )
2013-09-05 01:39:02 +00:00
report_note (
:host = > ip ,
:port = > rport ,
:proto = > 'tcp' ,
:sname = > ( ssl ? 'https' : 'http' ) ,
:ntype = > 'ntlm.enumeration.info' ,
2013-09-05 14:06:11 +00:00
:data = > { :uri = > tpath , :SMBName = > result [ :nbname ] , :SMBDomain = > result [ :nbdomain ] , :FQDNDomain = > result [ :dnsdomain ] , :FQDNName = > result [ :dnsserver ] } ,
2013-09-05 01:39:02 +00:00
:update = > :unique_data
)
return
end
end
end
2013-09-05 13:34:35 +00:00
def check_url ( test_uri )
2013-09-05 01:39:02 +00:00
begin
2013-09-05 14:06:11 +00:00
vprint_status ( " Checking #{ peer } URL #{ test_uri } " )
2013-09-05 01:39:02 +00:00
res = send_request_cgi ( {
'encode' = > true ,
2013-09-05 14:06:11 +00:00
'uri' = > " #{ test_uri } " ,
2013-09-05 01:39:02 +00:00
'method' = > 'GET' ,
'headers' = > { " Authorization " = > " NTLM TlRMTVNTUAABAAAAB4IIogAAAAAAAAAAAAAAAAAAAAAGAbEdAAAADw== " }
2013-09-05 13:34:35 +00:00
} , 20 )
2013-09-05 01:39:02 +00:00
return if res . nil?
vprint_status ( " Status: #{ res . code } " )
if res and res . code == 401 and res [ 'WWW-Authenticate' ] . match ( / ^NTLM /i )
hash = res [ 'WWW-Authenticate' ] . split ( 'NTLM ' ) [ 1 ]
#Parse out the NTLM and just get the Target Information Data
target = Rex :: Proto :: NTLM :: Message . parse ( Rex :: Text . decode_base64 ( hash ) ) [ :target_info ] . value ( )
# Retrieve Domain name subblock info
nbdomain = parse_ntlm_info ( target , " \x02 \x00 " , 0 )
# Retrieve Server name subblock info
nbname = parse_ntlm_info ( target , " \x01 \x00 " , nbdomain [ :new_offset ] )
# Retrieve DNS domain name subblock info
dnsdomain = parse_ntlm_info ( target , " \x04 \x00 " , nbname [ :new_offset ] )
# Retrieve DNS server name subblock info
dnsserver = parse_ntlm_info ( target , " \x03 \x00 " , dnsdomain [ :new_offset ] )
return {
:nbname = > nbname [ :message ] ,
:nbdomain = > nbdomain [ :message ] ,
:dnsdomain = > dnsdomain [ :message ] ,
:dnsserver = > dnsserver [ :message ]
}
end
rescue OpenSSL :: SSL :: SSLError
vprint_error ( " #{ peer } - SSL error " )
return
rescue Errno :: ENOPROTOOPT , Errno :: ECONNRESET , :: Rex :: ConnectionRefused , :: Rex :: HostUnreachable , :: Rex :: ConnectionTimeout , :: ArgumentError
vprint_error ( " #{ peer } - Unable to Connect " )
return
rescue :: Timeout :: Error , :: Errno :: EPIPE
vprint_error ( " #{ peer } - Timeout error " )
return
end
end
def parse_ntlm_info ( message , pattern , offset )
name_index = message . index ( pattern , offset )
offset = name_index . to_i
size = message [ offset + 2 ] . unpack ( 'C' ) . first
return {
:message = > message [ offset + 3 , size ] . gsub ( / \ 0 / , '' ) ,
:new_offset = > offset + size
}
end
end