Library smbauth
This module takes care of the authentication used in SMB (LM, NTLM, LMv2, NTLMv2).
There is a lot to this functionality, so if you're interested in how it works, read on. In SMB authentication, there are two distinct concepts. Each will be dealt with separately. There are:
- Stored hashes
- Authentication
What's confusing is that the same names are used for each of those.
Stored Hashes: Windows stores two types of hashes: Lanman and NT Lanman (or NTLM). Vista and later store NTLM only. Lanman passwords are divided into two 7-character passwords and used as a key in DES, while NTLM is converted to unicode and MD4ed.
The stored hashes can be dumped in a variety of ways (pwdump6, fgdump, Metasploit's
priv
module, smb-psexec.nse
, etc). Generally, two hashes are dumped together
(generally, Lanman:NTLM). Sometimes, Lanman is empty and only NTLM is given. Lanman
is never required.
The password hashes can be given instead of passwords when supplying credentials;
this is done by using the smbhash
argument. Either a pair of hashes
can be passed, in the form of Lanman:NTLM, or a single hash, which is assumed to
be NTLM.
Authentication: There are four types of authentication. Confusingly, these have the same names as stored hashes, but only slight relationships. The four types are Lanmanv1, NTLMv1, Lanmanv2, and NTLMv2. By default, Lanmanv1 and NTLMv1 are used together in most applications. These Nmap scripts default to NTLMv1 alone, except in special cases, but it can be overridden by the user.
Lanmanv1 and NTLMv1 both use DES for their response. The DES mixes a server challenge with the hash (Lanman hash for Lanmanv1 response and NTLMv1 hash for NTLM response). The way the challenge is DESed with the hashes is identical for Lanmanv1 and NTLMv1, the only difference is the starting hash (Lanman vs NTLM).
Lanmanv2 and NTLMv2 both use HMAC-MD5 for their response. The HMAC-MD5 mixes a server challenge and a client challenge with the NTLM hash, in both cases. The difference between Lanmanv2 and NTLMv2 is the length of the client challenge; Lanmanv2 has a maximum client challenge of 8 bytes, whereas NTLMv2 doesn't limit the length of the client challenge.
The primary advantage to the 'v2' protocols is the client challenge -- by incorporating a client challenge, a malicious server can't use a precomputation attack.
In addition to hashing the passwords, messages are also signed, by default, if a v1 protocol is being used (I (Ron Bowes) couldn't get signatures to work on v2 protocols; if anybody knows how I'd love to implement it).
Source: https://svn.nmap.org/nmap/nselib/smbauth.lua
Script Arguments
- smbpassword
The password to connect with. Be cautious with this, since some servers will lock accounts if the incorrect password is given. Although it's rare that the Administrator account can be locked out, in the off chance that it can, you could get yourself in trouble. To use a blank password, leave this parameter off altogether.
- smbhash
A password hash to use when logging in. This is given as a single hex string (32 characters) or a pair of hex strings (both 32 characters, optionally separated by a single character). These hashes are the LanMan or NTLM hash of the user's password, and are stored on disk or in memory. They can be retrieved from memory using the fgdump or pwdump tools.
- smbnoguest
Use to disable usage of the 'guest' account.
- smbdomain
The domain to log in with. If you aren't in a domain environment, then anything will (should?) be accepted by the server.
- smbtype
The type of SMB authentication to use. These are the possible options:
v1
: Sends LMv1 and NTLMv1.LMv1
: Sends LMv1 only.NTLMv1
: Sends NTLMv1 only (default).v2
: Sends LMv2 and NTLMv2.LMv2
: Sends LMv2 only.NTLMv2
: Doesn't exist; the protocol doesn't support NTLMv2 alone. The default,NTLMv1
, is a pretty decent compromise between security and compatibility. If you are paranoid, you might want to usev2
orlmv2
for this. (Actually, if you're paranoid, you should be avoiding this protocol altogether!). If you're using an extremely old system, you might need to set this tov1
orlm
, which are less secure but more compatible. For information, seesmbauth.lua
.
- smbusername
The SMB username to log in with. The forms "DOMAIN\username" and "username@DOMAIN" are not understood. To set a domain, use the
smbdomain
argument.
Functions
- add_account (host, username, domain, password, password_hash, hash_type, is_admin)
Writes the given account to the registry.
- calculate_signature (mac_key, data)
Create an 8-byte message signature that's sent with all SMB packets.
- get_account (host)
Retrieve the current set of credentials set in the registry.
- get_host_info_from_security_blob (security_blob)
Gets host info from a security blob
- get_password_response (ip, username, domain, password, password_hash, hash_type, challenge, is_extended)
Generate the Lanman and NTLM password hashes.
- get_security_blob (security_blob, ip, username, domain, password, password_hash, hash_type, flags)
Generate an NTLMSSP security blob.
- init_account (host)
Initialize the host's account table.
- lm_create_mac_key (lm_hash, lm_response, is_extended)
Create the LM mac key, which is used for message signing.
- lm_create_response (lanman, challenge)
Create the Lanman response to send back to the server.
- lmv2_create_response (ntlm, username, domain, challenge)
Create the LMv2 response, which can be sent back to the server.
- next_account (host, num)
Try the next stored account for this host
- ntlm_create_hash (password)
Generate the NTLMv1 hash.
- ntlm_create_mac_key (ntlm_hash, ntlm_response, is_extended)
Create the NTLM mac key, which is used for message signing.
- ntlm_create_response (ntlm, challenge)
Create the NTLM response to send back to the server.
- ntlmv2_create_hash (ntlm, username, domain)
Create the NTLMv2 hash.
- ntlmv2_create_response (ntlm, username, domain, challenge, client_challenge_length)
Create the NTLMv2 response, which can be sent back to the server.
- ntlmv2_session_response (ntlm_password_hash, challenge)
Generates the ntlmv2 session response. It starts by generatng an 8 byte random client nonce, it is padded to 24 bytes. The padded value is the lanman response. A session nonce is made by concatenating the server challenge and the client nonce. The ntlm session hash is first 8 bytes of the md5 hash of the session nonce. The ntlm response is the lm response with session hash as challenge.
Tables
- host_info
Host information for NTLM security
Functions
- add_account (host, username, domain, password, password_hash, hash_type, is_admin)
-
Writes the given account to the registry.
There are several places where accounts are stored:
- registry['usernames'][username] => true
- registry['smbaccounts'][username] => password
- registry[ip]['smbaccounts'] => array of table containing 'username', 'password', and 'is_admin'
The final place, 'smbaccount', is reserved for the "best" account. This is an administrator account, if one's found; otherwise, it's the first account discovered that isn't
guest
.This has to be called while no SMB connections are made, since it potentially makes its own connection.
Parameters
- host
- The host object.
- username
- The username to add.
- domain
- The domain to add.
- password
- The password to add.
- password_hash
- The password hash to add.
- hash_type
- The hash type to use.
- is_admin
- [optional] Set to 'true' the account is known to be an administrator.
- calculate_signature (mac_key, data)
-
Create an 8-byte message signature that's sent with all SMB packets.
Parameters
- mac_key
- The key used for authentication. It's the concatenation of the session key and the response hash.
- data
- The packet to generate the signature for. This should be the packet that's about to be sent, except with the signature slot replaced with the sequence number.
Return value:
The 8-byte signature. The signature is equal to the first eight bytes of md5(mac_key .. smb_data) - get_account (host)
-
Retrieve the current set of credentials set in the registry.
If these fail,
next_account
should be called.Parameters
- host
- The host object.
Return values:
- status true or false. If false, the next return value is an error message and no other values are returned.
- username
- domain
- password
- password_hash
- hash_type
See also:
- get_host_info_from_security_blob (security_blob)
-
Gets host info from a security blob
Parameters
- security_blob
- The NTLM security blob
Return value:
A host_info table containing the data in the blob.See also:
- get_password_response (ip, username, domain, password, password_hash, hash_type, challenge, is_extended)
-
Generate the Lanman and NTLM password hashes.
The password itself is taken from the function parameters, the script arguments, and the registry (in that order). If no password is set, then the password hash is used (which is read from all the usual places). If neither is set, then a blank password is used.
The output passwords are hashed based on the hash type.
Parameters
- ip
- The ip address of the host, used for registry lookups.
- username
- The username, which is used for v2 passwords.
- domain
- The username, which is used for v2 passwords.
- password
- [optional] The overriding password.
- password_hash
- [optional] The overriding password hash. Shouldn't be set if password is set.
- hash_type
- The way in which to hash the password.
- challenge
- The server challenge.
- is_extended
- Set to 'true' if extended security negotiations are being used (this has to be known for the message-signing key to be generated properly).
Return values:
- lm_response, to be send directly back to the server
- ntlm_response, to be send directly back to the server
- get_security_blob (security_blob, ip, username, domain, password, password_hash, hash_type, flags)
-
Generate an NTLMSSP security blob.
Parameters
- security_blob
- The server's security blob, or nil if this is the first message
- ip
- The ip address of the host, used for registry lookups.
- username
- The username, which is used for v2 passwords.
- domain
- The username, which is used for v2 passwords.
- password
- [optional] The overriding password.
- password_hash
- [optional] The overriding password hash. Shouldn't be set if password is set.
- hash_type
- The way in which to hash the password.
- flags
- The NTLM flags as a number
- init_account (host)
-
Initialize the host's account table.
Create the account table with the anonymous and guest users, as well as the user given in the script's arguments, if there is one.
Parameters
- host
- The host object.
- lm_create_mac_key (lm_hash, lm_response, is_extended)
-
Create the LM mac key, which is used for message signing.
For basic authentication, it's the first 8 bytes of the lanman hash, followed by 8 null bytes, followed by the lanman response; for extended authentication, this is just the first 8 bytes of the lanman hash followed by 8 null bytes.
Parameters
- lm_hash
- The LM hash.
- lm_response
- The LM response.
- is_extended
- Should be set if extended security negotiations are being used.
Return value:
The LM mac key - lm_create_response (lanman, challenge)
-
Create the Lanman response to send back to the server.
To do this, the Lanman password is padded to 21 characters and split into three 7-character strings. Each of those strings is used as a key to encrypt the server challenge. The three encrypted strings are concatenated and returned.
Parameters
- lanman
- The LMv1 hash
- challenge
- The server's challenge.
Return values:
- true on success, or false on error
- The client challenge response, or an error message
- lmv2_create_response (ntlm, username, domain, challenge)
-
Create the LMv2 response, which can be sent back to the server.
This is identical to the
NTLMv2
function, except that it uses an 8-byte client challenge.The reason for LMv2 is a long and twisted story. Well, not really. The reason is basically that the v1 hashes are always 24-bytes, and some servers expect 24 bytes, but the NTLMv2 hash is more than 24 bytes. So, the only way to keep pass-through compatibility was to have a v2-hash that was guaranteed to be 24 bytes. So LMv2 was born -- it has a 16-byte hash followed by the 8-byte client challenge, for a total of 24 bytes. And now you've learned something
Parameters
- ntlm
- The NVLMv1 hash.
- username
- The username we're using.
- domain
- The domain.
- challenge
- The server challenge.
Return values:
- true on success, or false on error
- The LMv2 response, or an error message
- next_account (host, num)
-
Try the next stored account for this host
Parameters
- host
- The host table
- num
- If nil, the next account is chosen. If a number, the account at that index is chosen
- ntlm_create_hash (password)
-
Generate the NTLMv1 hash.
This hash is quite a bit better than LMv1, and is far easier to generate. Basically, it's the MD4 of the Unicode password.
Parameters
- password
- the password to hash
Return values:
- true on success, or false on error
- The NTLMv1 hash
- ntlm_create_mac_key (ntlm_hash, ntlm_response, is_extended)
-
Create the NTLM mac key, which is used for message signing.
For basic authentication, this is the md4 of the NTLM hash, concatenated with the response hash; for extended authentication, this is just the md4 of the NTLM hash.
Parameters
- ntlm_hash
- The NTLM hash.
- ntlm_response
- The NTLM response.
- is_extended
- Should be set if extended security negotiations are being used.
Return value:
The NTLM mac key - ntlm_create_response (ntlm, challenge)
-
Create the NTLM response to send back to the server.
This is actually done the exact same way as the Lanman hash, so I call the
Lanman
function.Parameters
- ntlm
- The NTLMv1 hash
- challenge
- The server's challenge.
Return values:
- true on success, or false on error
- The client challenge response, or an error message
- ntlmv2_create_hash (ntlm, username, domain)
-
Create the NTLMv2 hash.
The NTLMv2 hash is based on the NTLMv1 hash (for easy upgrading), the username, and the domain. Essentially, the NTLM hash is used as a HMAC-MD5 key, which is used to hash the unicode domain concatenated with the unicode username.
Parameters
- ntlm
- The NTLMv1 hash.
- username
- The username we're using.
- domain
- The domain.
Return values:
- true on success, or false on error
- The NTLMv2 hash or an error message
- ntlmv2_create_response (ntlm, username, domain, challenge, client_challenge_length)
-
Create the NTLMv2 response, which can be sent back to the server.
This is done by using the HMAC-MD5 algorithm with the NTLMv2 hash as a key, and the server challenge concatenated with the client challenge for the data. The resulting hash is concatenated with the client challenge and returned.
The "proper" implementation for this uses a certain structure for the client challenge, involving the time and computer name and stuff (if you don't do this, Wireshark tells you it's a malformed packet). In my tests, however, I couldn't get Vista to recognize a client challenge longer than 24 bytes, and this structure was guaranteed to be much longer than 24 bytes. So, I just use a random string generated by OpenSSL. I've tested it on every Windows system from Windows 2000 to Windows Vista, and it has always worked.
Parameters
- ntlm
- The NVLMv1 hash.
- username
- The username we're using.
- domain
- The domain.
- challenge
- The server challenge.
- client_challenge_length
- number of random bytes of client challenge to use
Return values:
- true on success, or false on error
- The NTLMv2 response, or an error message
- ntlmv2_session_response (ntlm_password_hash, challenge)
-
Generates the ntlmv2 session response. It starts by generatng an 8 byte random client nonce, it is padded to 24 bytes. The padded value is the lanman response. A session nonce is made by concatenating the server challenge and the client nonce. The ntlm session hash is first 8 bytes of the md5 hash of the session nonce. The ntlm response is the lm response with session hash as challenge.
Parameters
- ntlm_password_hash
- The md4 hash of the utf-16 password.
- challenge
- The challenge sent by the server.
Tables
- host_info
Host information for NTLM security
Fields
- target_realm
- Target Name Data
- netbios_computer_name
- Server name
- netbios_domain_name
- Domain name
- fqdn
- DNS server name
- dns_domain_name
- DNS domain name
- dns_forest_name
- DNS tree name
- timestamp
- Timestamp