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 use v2 or lmv2 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 to v1 or lm, which are less secure but more compatible. For information, see smbauth.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:

  1. status true or false. If false, the next return value is an error message and no other values are returned.
  2. username
  3. domain
  4. password
  5. password_hash
  6. 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:

  1. lm_response, to be send directly back to the server
  2. 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:

  1. true on success, or false on error
  2. 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:

  1. true on success, or false on error
  2. 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:

  1. true on success, or false on error
  2. 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:

  1. true on success, or false on error
  2. 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:

  1. true on success, or false on error
  2. 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:

  1. true on success, or false on error
  2. 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