NTLM

NT Lan Manager (NTLM/MS-NLMP) is the name of a family of security protocols consisting of

  • LM

  • NTLMv1

  • NTLMv2

NTLM is a connection-oriented protocol, its connection-less variant is called MS-NLMP. It's worth noting that both domain-joined and workgroup computers can utilize NTLM for authentication.

The protocol is used on various Windows-based networks to authenticate remote users and optionally provide session security when requested by the application. The NTLM security protocols are all embedded protocols, meaning that although NTLM has messages and a state machine like other protocols, it does not have a network protocol stack layer allowing any protocol with a defined layer in the network stack such as SMB, HTTP / HTTPS, and LDAP / LDAPS to utilize it.

NTLM is a challenge-response protocol that uses nonces, pseudo-random numbers generated for one-time use, as a defensive mechanism against replaying attacks.

Unlike normal protocol implementations, NTLM's nature means that the protocol is best implemented as a function library that can be called by application protocols rather than as a layer in a network protocol stack. This happens through Security Support Provider Interface (SSPI), an API that allows connected applications to call one of several security providers to establish authenticated connections and to exchange data securely over those connections.

A security support provider (SSP) is a DLL responsible for implementing the SSPI by exposing one or more security packages to applications with each security package providing mappings between an application's SSPI function calls and an actual security model's functions.

The NTLM SSP (located at %windir%\system32\msv1_0.dll) is a binary messaging protocol utilized by SSPI to facilitate NTLM challenge-response authentication and to negotiate options for integrity and confidentiality. The SSP encompasses both the NTLM and NTLMv2.

From a security standpoint, NTLM allows the plaintext credentials or cryptographic keys not to be sent over the wire (just like Kerberos) as the keys are either shared with the DC before-hand (in AD environments). Moreover, the NTLM version used in the authentication process isn't dynamically chosen during authentication, instead it's pre-configured through security policies and registry settings (Security Settings > Local Policies > Security Options > Network security: LAN Manager authentication level).

Password Hashing

Hash/Protocol

Cryptographic technique

Mutual Authentication

Message Type

Trusted Third Party

NTLM

Symmetric key cryptography

No

Random number

Domain Controller

NTLMv1

Symmetric key cryptography

No

MD4 hash, random number

Domain Controller

NTLMv2

Symmetric key cryptography

No

MD4 hash, random number

Domain Controller

LM hashes

LAN Manager (LM or LANMAN) hashes are the oldest password storage mechanism used by the Windows operating system. LM debuted in 1987 on the OS/2 operating system. If in use, they are stored in the SAM database on a Windows host and the NTDS.DIT database on a Domain Controller. Due to significant security weaknesses in the hashing algorithm used for LM hashes, it has been turned off by default since Windows Vista/Server 2008. However, it is still common to encounter, especially in large environments where older systems are still used. Passwords using LM are limited to a maximum of 14 characters. Passwords are not case sensitive and are converted to uppercase before generating the hashed value, limiting the keyspace to a total of 69 characters making it relatively easy to crack these hashes using a tool such as Hashcat.

Before hashing, a 14 character password is first split into two seven-character chunks. If the password is less than fourteen characters, it will be padded with NULL characters to reach the correct value. Two DES keys are created from each chunk. These chunks are then encrypted using the string KGS!@#$%, creating two 8-byte ciphertext values. These two values are then concatenated together, resulting in an LM hash. This hashing algorithm means that an attacker only needs to brute force seven characters twice instead of the entire fourteen characters, making it fast to crack LM hashes on a system with one or more GPUs. If a password is seven characters or less, the second half of the LM hash will always be the same value and could even be determined visually without even needed tools such as Hashcat. The use of LM hashes can be disallowed using Group Policy. An LM hash takes the form of 299bd128c1101fd6.

Windows operating systems prior to Windows Vista and Windows Server 2008 (Windows NT4, Windows 2000, Windows 2003, Windows XP) stored both the LM hash and the NTLM hash of a user's password by default.

The following are the instructions used to hash a password using the LM algorithm

  1. Convert all lower case to upper case

  2. Pad password to 14 characters with NULL characters

  3. Split the password to two 7 character chunks

  4. Create two DES keys from each 7 character chunk

  5. DES encrypt the string "KGS!@#$%" with these two chunks

  6. Concatenate the two DES encrypted strings. This is the LM hash.

NTHash (NTLM) hashes

NT LAN Manager (NTLM) hashes are used on modern Windows systems. It is a challenge-response authentication protocol and uses three messages to authenticate: a client first sends a NEGOTIATE_MESSAGE to the server, whose response is a CHALLENGE_MESSAGE to verify the client's identity. Lastly, the client responds with an AUTHENTICATE_MESSAGE. These hashes are stored locally in the SAM database or the NTDS.DIT database file on a Domain Controller. The protocol has two hashed password values to choose from to perform authentication: the LM hash (as discussed above) and the NT hash, which is the MD4 hash of the little-endian UTF-16 value of the password. The algorithm can be visualized as: MD4(UTF-16-LE(password)).

Even though they are considerably stronger than LM hashes (supporting the entire Unicode character set of 65,536 characters), they can still be brute-forced offline relatively quickly using a tool such as Hashcat. GPU attacks have shown that the entire NTLM 8 character keyspace can be brute-forced in under 3 hours. Longer NTLM hashes can be more challenging to crack depending on the password chosen, and even long passwords (15+ characters) can be cracked using an offline dictionary attack combined with rules. NTLM is also vulnerable to the pass-the-hash attack, which means an attacker can use just the NTLM hash (after obtaining via another successful attack) to authenticate to target systems where the user is a local admin without needing to know the cleartext value of the password.

An NT hash takes the form of b4b9b02e6f09a9bd760f388b67351e2b, which is the second half of the full NTLM hash. An NTLM hash looks like this:

Rachel:500:aad3c435b514a4eeaad3b935b51304fe:e46b9e548fa0d122de7f59fb6d48eaa2:::

Looking at the hash above, we can break the NTLM hash down into its individual parts:

  • Rachel is the username

  • 500 is the Relative Identifier (RID). 500 is the known RID for the administrator account

  • aad3c435b514a4eeaad3b935b51304fe is the LM hash and, if LM hashes are disabled on the system, can not be used for anything

  • e46b9e548fa0d122de7f59fb6d48eaa2 is the NT hash. This hash can either be cracked offline to reveal the cleartext value (depending on the length/strength of the password) or used for a pass-the-hash attack.

During NTLM authentication, a client can prove to a server its identity by encrypting with its password some piece of information provided by the server. So the only thing the attacker has to do is to let the client do its work, and passing the messages from the client to the server, and the replies from the server to the client.

All the client has to send to the server, the attacker will receive it, and he will send the messages back to the real server, and all the messages that the server sends to the client, the attacker will also receive them, and he will forward them to the client, as is.

So attacks like Pass-The-Hash work following this protocol and using the same secret as the legitimate user, but instead of hashing the password, the attacker can just use the raw NTLM hash

NTLMv1 (Net-NTLMv1) hashes

The NTLM protocol performs a challenge/response between a server and client using the NT hash. NTLMv1 uses both the NT and the LM hash, which can make it easier to "crack" offline after capturing a hash using a tool such as Responder or via an NTLM relay attack (both of which are out of scope for this module and will be covered in later modules on Lateral Movement). The protocol is used for network authentication, and the Net-NTLMv1 hash itself is created from a challenge/response algorithm. The server sends the client an 8-byte random number (challenge), and the client returns a 24-byte response. These hashes can NOT be used for pass-the-hash attacks. The algorithm looks as follows:

C = 8-byte server challenge, random
K1 | K2 | K3 = LM/NT-hash | 5-bytes-0
response = DES(K1,C) | DES(K2,C) | DES(K3,C)

An example of a full NTLMv1 hash looks like:

u4-netntlm::kNS:338d08f8e26de93300000000000000000000000000000000:9526fb8c23a90751cdd619b6cea564742e1e4bf33006ba41:cb8086049ec4736c

NTLMv1 was the building block for modern NTLM authentication. Like any protocol, it has flaws and is susceptible to cracking and other attacks. Now let us move on and take a look at NTLMv2 and see how it improves on the foundation that version one set.

NTLMv2 (Net-NTLMv2) hashes

The NTLMv2 protocol was first introduced in Windows NT 4.0 SP4 and was created as a stronger alternative to NTLMv1. It has been the default in Windows since Server 2000. It is hardened against certain spoofing attacks that NTLMv1 is susceptible to. NTLMv2 sends two responses to the 8-byte challenge received by the server. These responses contain a 16-byte HMAC-MD5 hash of the challenge, a randomly generated challenge from the client, and an HMAC-MD5 hash of the user's credentials. A second response is sent, using a variable-length client challenge including the current time, an 8-byte random value, and the domain name. The algorithm is as follows:

SC = 8-byte server challenge, random
CC = 8-byte client challenge, random
CC* = (X, time, CC2, domain name)
v2-Hash = HMAC-MD5(NT-Hash, user name, domain name)
LMv2 = HMAC-MD5(v2-Hash, SC, CC)
NTv2 = HMAC-MD5(v2-Hash, SC, CC*)
response = LMv2 | CC | NTv2 | CC*

An example of an NTLMv2 hash is:

admin::N46iSNekpT:08ca45b7d7ea58ee:88dcbe4446168966a153a0064958dac6:5c7830315c7830310000000000000b45c67103d07d7b95acd12ffa11230e0000000052920b85f78d013c31cdb3b92f5d765c783030

We can see that developers improved upon V1 by making NTLMv2 harder to crack and giving it a more robust algorithm made up of multiple stages. We have one more authentication mechanism to discuss before moving on. This method is of note to us because it does not require a persistent network connection to work.

More on how the responses are sent and calculated below.

Authentication Workflow

The NTLM authentication workflow for domain-joined computers starts with the client exchanging implementation-specific application protocol messages with the server (where the desired service is), indicating that it wants to authenticate. Subsequently, the client and server exchange three NTLM-specific messages during authentication (embedded in application protocol messages):

  1. NEGOTIATE_MESSAGE (also known as Type 1 message)

  2. CHALLENGE_MESSAGE (also known as Type 2 message)

  3. AUTHENTICATE_MESSAGE (also known as Type 3 message)

Once it receives the AUTHENTICATE_MESSAGE, and because it does not possess the client's secret key, the server delegates the verification of the user's identity to a DC (a procedure known as Pass-through authentication) by invoking NetrLogonSamLogonWithFlags, which contains NETLOGON_NETWORK_INFO, a data structure populated with the various fields that the DC requires to verify the user. If authentication is successful, the DC returns a NETLOGON_VALIDATION_SAM_INFO4 data structure to the server, and the server establishes an authenticated session with the client; otherwise, the DC returns an error, and the server might return an error message to the client, or, it can simply terminate the connection.

The diagram below is NTLM's pass-through authentication:

The only difference for workgroup authentication is that the server verifies the user's identity instead of delegating it to the DC:

NTLM Messages

Each NTLM message is variable-length, containing a fixed-length header and a variable-sized message payload. The header always starts with the Signature and MessageType fields, and depending on the latter, messages can have additional message-dependent fixed-length fields. A variable-length message payload follows these fields.

Field
Meaning

Signature

An 8-byte NULL-terminated ASCII string always set to [N, T, L, M, S, S, P, \0].

MessageType

A 4-byte unsigned integer always set to either 0x00000001 (NtLmNegotiate) to indicate that the NTLM message is a NEGOTIATE_MESSAGE or 0x00000002 (NtLmChallenge) to indicate that the NTLM message is a CHALLENGE_MESSAGE or 0x00000003 (NtLmAuthenticate) to indicate that the NTLM message is an AUTHENTICATE_MESSAGE.

MessageDependentFields

A variable-length field that contains the NTLM message contents.

payload

A variable-length field that contains a message-dependent number of individual payload messages, referenced by byte offsets in MessageDependentFields.

NEGOTIATE_MESSAGE

The NEGOTIATE_MESSAGE is the first NTLM-specific message, sent by the client indicating that it wants to authenticate to the server and specifying its supported/requested NTLM options. It contains four message-dependent fixed-length fields. One important field to know about is NegotiateFlags; this 4-bytes field, present in all three NTLM messages and not exclusive to NEGOTIATE_MESSAGE, is a NEGOTIATE structure consisting of 32 1-bit flags that allow indicating which NTLM capabilities are supported/requested by the sender.

CHALLENGE_MESSAGE

The CHALLENGE_MESSAGE is the second NTLM-specific message, sent by the server to the client to state the NTLM options it can support and challenge the client to prove its identity. It contains six message-dependent fixed-length fields, two important to know about, NegotiateFlags and ServerChallenge. NegotiateFlags holds the flags the server has chosen from the options offered/requested by the client in NegotiateFlags of the NEGOTIATE_MESSAGE. At the same time, ServerChallenge is a 64-bit nonce that holds the NTLM challenge generated by the server.

Some tools, such as NTLM Challenger, ntlm-info, NTLMRecon, and DumpNTLMInfo.py perform reconnaissance against endpoints/hosts that accept NTLM authentication by parsing the information returned within the CHALLENGE_MESSAGE (review its other fields to know why this is possible):

python3 examples/DumpNTLMInfo.py 172.16.117.3

Impacket v0.12.0.dev1+20230803.144057.e2092339 - Copyright 2023 Fortra

[+] SMBv1 Enabled   : False
[+] Prefered Dialect: SMB 3.0
[+] Server Security : SIGNING_ENABLED | SIGNING_REQUIRED
[+] Max Read Size   : 8.0 MB (8388608 bytes)
[+] Max Write Size  : 8.0 MB (8388608 bytes)
[+] Current Time    : 2023-08-14 17:39:26.822236+00:00
[+] Name            : DC01
[+] Domain          : DOMAIN
[+] DNS Tree Name   : DOMAIN.COM
[+] DNS Domain Name : DOMAIN.COM
[+] DNS Host Name   : DC01.DOMAIN.COM
[+] OS              : Windows NT 10.0 Build 17763
[+] Null Session    : True

AUTHENTICATE_MESSAGE

The AUTHENTICATE_MESSAGE is the third and last NTLM-specific message, sent by the client to the server to prove its possession of the shared secret key. It contains nine message-dependent fixed-length fields, two important to know about, LmChallengeResponseFields and NtChallengeResponseFields. For the pseudocode provided by MS-NLMP, we will also refer to the relevant implementation of impacket's NTLM.

NTLMv1 Response Calculation

If NTLMSSP_NEGOTIATE_LM_KEY (the G bit in NEGOTIATE) was agreed upon by the server and client in NegotiateFlags, then, if NTLMv1 is used, LmChallengeResponseFields contains a LM_RESPONSE structure, otherwise, if NTLMv2 is used, LmChallengeResponseFields will contain a LMv2_RESPONSE structure. LM_RESPONSE contains one field, which is Response, a 24-byte array of unsigned char that contains the client's LmChallengeResponse. While for LMv2_RESPONSE, it contains two fields, Response and ChallengeFromClient; Response is a 16-byte array of unsigned char that contains the clients LM challenge-response, while ChallengeFromClient is an 8-byte array of unsigned char that contains a challenge generated by the client. To compute the Response field of LM_RESPONSE or LMv2_RESPONSE, MS-NLMP provides pseudocode.

For NTLMv1 authentication, NTOWFv1 (used only by NTLMv1 and implemented in the compute_nthash function), is an NT LAN Manager (NT) one-way function that creates a hash based on the user's password to generate a principal's security key: instead of using the user's plaintext password, the resultant hash of this function gets used in computing the response. LMOWFv1 (implemented in the compute_lmhash function), used only by LM and NTLMv1, is an NT LAN Manager (LM) one-way function that also creates a hash based on the user's password to generate a principal's security key. The client uses these two functions to calculate the response it returns to the server; the pseudocode for the response calculation is implemented in the function computeResponseNTLMv1.

For NtChallengeResponseFields, if NTLMv1 is used, NtChallengeResponse will contain an NTLM_RESPONSE structure, otherwise, if NTLMv2 is used, then NtChallengeResponse will contain a NTLMv2_RESPONSE structure; NTLM_RESPONSE contains one field, which is Response, a 24-byte array of unsigned char that contains the client's NtChallengeResponse. For NTLMv2_RESPONSE, it contains two fields, Response and a NTLMv2_CLIENT_CHALLENGE structure; Response is a 16-byte array of unsigned char that contains the client's NtChallengeResponse, while NTLMv2_CLIENT_CHALLENGE is a variable-length byte array that contains eight fixed-length variables, including ChallengeFromClient. If we were to capture an NTLMv1 hash using Responder, it will display it using the format User::HostName:LmChallengeResponse:NtChallengeResponse:ServerChallenge:

[SMB] NTLMv1 Client   : 172.19.117.36
[SMB] NTLMv1 Username : Support1
[SMB] NTLMv1 Hash     : Support1::WIN-OLMHXGAP0V2:e2dL3196O8f55fB6:Q49S19A2937J6XC3CKA418EI4958OHB9:xF2K324O5L6Q7V8C

NTLMv2 Response Calculation

For the response calculation of NTLMv2 authentication, NTOWFv2 and LMOWFv2 (both are version-dependent and only used by NTLMv2, they are implemented in the functions LMOWFv2 and NTOWFv2, respectively) are the one-way functions used to create a hash based on the user's password to generate a principal's security key. With these two functions, the client calculates the response it returns to the server as described in pseudocode (implemented in the function computeResponseNTLMv2). If we were to capture an NTLMv2 hash using Responder, it will display it using the format User::Domain:ServerChallenge:Response:NTLMv2_CLIENT_CHALLENGE:

[SMB] NTLMv2-SSP Client   : 172.19.117.55
[SMB] NTLMv2-SSP Username : DOMAIN\Support2
[SMB] NTLMv2-SSP Hash     : Support2::DOMAIN:e2d2339638fc5fd6:D4979A923DD76BC3CFA418E94958E2B0:010100000000000000E0550D97CCD901509F9CE743AB58760000000002000800350034005800360001001E00570049004E002D00390038004B005100480054005300390048004200550004003400570049004E002D00390038004B00510048005400530039004800420055002E0035003400580036002E004C004F00430041004C000300140035003400580036002E004C004F00430041004C000500140035003400580036002E004C004F00430041004C000700080000E0550D97CCD901060004000200000008003000300000000000000000000000004000002DB95E9E27F0AD66CAA477372F555B500CFEA9C5A231FC68F0DA4FABFF76607E0A001000000000000000000000000000000000000900240063006900660073002F003100370032002E00310036002E003100310037002E00330030000000000000000000

NTLM Session Security

If the client and server negotiate it, session security provides message integrity (signing) and message confidentiality (sealing). The NTLM protocol itself does not provide session security; instead, SSPI provides it. NTLMv1, supplanted by NTLMv2, does not support sealing but only signing; therefore, Microsoft strongly recommends against its usage (and the deprecated LM authentication protocol also).

Message Signing and Sealing

Message signing provides message integrity and helps against relay attacks; it is a critical security feature designed to enhance the security of messages sent between the client and server during NTLM communications. When session signing is negotiated, the client and server negotiate a session key to sign all messages exchanged. The session key is generated using a combination of the client's and server's challenge messages and the user's password hash. Once the session key is established, all messages between the client and server are signed using a MAC. The MAC is generated by applying a cryptographic algorithm to the message and the session key. The server can verify the MAC by using the same algorithm as the message and the session key and comparing the result to the MAC provided by the client. Although an adversary might be eavesdropping, they don't possess the user's password hash since it is never transmitted over the wire, and therefore cannot sign messages. Based on the blog post The Basics of SMB Signing (covering both SMB1 and SMB2), we can know the default SMB signing settings for hosts in the network depending on the SMB version they are running. Except for SMB1, which has three possible settings, Required, Enabled, or Disabled, SMB2 and SMB3 only have Required or Not Required:

Host

Default Signing Setting

SMB1 Client

Enabled

SMB1 Server

Disabled

SMB2 & SMB3 Clients

Not Required

SMB2 & SMB3 Servers

Not Required

Domain Controllers

Required

Due to the ever-lasting abuse of the default SMB signing settings by adversaries, Microsoft released an update to enforce SMB signing on Windows 11 Insider editions (and later on for major releases). Microsoft decided, for a better security stature, to finally let go of the legacy behavior where Windows 10 and 11 required SMB signing by default only when connecting to shares named SYSVOL and NETLOGON and where DCs required SMB signing when any client connected to them. Ned Pyle, a Principal Program Manager at Microsoft, wrote the following regretful statement in the post SMB signing required by default in Windows Insider:

"SMB encryption is far more secure than signing, but environments still run legacy systems that don't support SMB 3.0 and later. If I could time travel to the 1990s, SMB signing would've always been on and we'd have introduced SMB encryption much sooner; sadly, I was both in high school and not in charge. We'll continue to push out more secure SMB defaults and many new SMB security options in the coming years; I know they can be painful for application compatibility and Windows has a legacy of ensuring ease of use, but security cannot be left to chance."

Message sealing provides message confidentiality by implementing a symmetric-key encryption mechanism; it ensures that the content of the messages exchanged between the client and server remains secure and that adversaries cannot read or tamper with them. In the context of NTLM, sealing also implies signing because every sealed message is also signed.

Extended Protection for Authentication (EPA)

Extended Protection for Authentication (EPA), based on RFC 5056, is a feature introduced in Windows Server 2008 and later versions that enhance the security of NTLM authentication. When EPA is enabled, the client and server establish a secure channel using a channel binding token (CBT). The CBT binds the authentication to the specific channel characteristics, such as the IP address and port, preventing the authentication from replaying on a different channel. EPA is designed to work with SMB and HTTP protocols, providing additional security for applications and services that rely on NTLM authentication; however, it requires the client and server to support it to establish a secure channel.

Domain Cached Credentials (MSCache2)

In an AD environment, the authentication methods mentioned in this section and the previous require the host we are trying to access to communicate with the "brains" of the network, the Domain Controller. Microsoft developed the MS Cache v1 and v2 algorithm (also known as Domain Cached Credentials (DCC) to solve the potential issue of a domain-joined host being unable to communicate with a domain controller (i.e., due to a network outage or other technical issue) and, hence, NTLM/Kerberos authentication not working to access the host in question. Hosts save the last ten hashes for any domain users that successfully log into the machine in the HKEY_LOCAL_MACHINE\SECURITY\Cache registry key. These hashes cannot be used in pass-the-hash attacks. Furthermore, the hash is very slow to crack with a tool such as Hashcat, even when using an extremely powerful GPU cracking rig, so attempts to crack these hashes typically need to be extremely targeted or rely on a very weak password in use. These hashes can be obtained by an attacker or pentester after gaining local admin access to a host and have the following format: $DCC2$10240#bjones#e4e938d12fe5974dc42a90120bd9c90f. It is vital as penetration testers that we understand the varying types of hashes that we may encounter while assessing an AD environment, their strengths, weaknesses, how they can be abused (cracking to cleartext, pass-the-hash, or relayed), and when an attack may be futile (i.e., spending days attempting to crack a set of Domain Cached Credentials).

Last updated