I’m in the midst of trying to phase out non-Kerberos authentication traffic in our domain, because it’s time. MS has offered Kerberos since Windows 2000, and the pre-Kerberos options (LANMan, NTLMv1, NTLMv2) are woefully insecure. In fact, MS stopped recommending NTLM for use in applications in 2010. It’s still widely in use for compatibility reasons.
The Protocols
LANMan
LANMan, or LAN Manager, was offered in 1987 and can be easily broken. Among other issues:
- A LANMan password is not case-sensitive. Everything is cast to uppercase before the hash is created. This dramatically reduces the characters that need to be bruteforced, as lowercase isn’t a required set (reducing the total characters by 26).
- When first created, the implementation presumed that passwords woud never be longer than 7 characters, so a total of eight bytes are used to store it - the seven password characters plus a parity byte. Of course, this quickly became a problem, so the password length was increased to use 16 bytes. But in order to remain backwards compatible, this is implemented as 2x 8-byte fields (7 password characters + 1 parity byte). Any password shorter than 14 charafters will have unused bytes filled with NULLs.
If the password is seven characters or less, the entire second 8-byte field will be full of NULLs, which means the attacker only has to break one 7-character password. Even if the password takes a full 14 characters, the attacker doesn’t have to break that, they are actually breaking 2 separate seven-character passwords, which is magnitudes of order faster.
NTLM v1
New Technology LAN Manager (NTLM) is the default authentication protocol for NT 4.0. It’s a challenge/response-based protocol but has issues as well:
- The challenge issued by NTLMv1 is always a 16-byte random number.
- It used a DES algorithm for encryption of the challenge (with the user’s hash). DES is built for speed, which makes decryption by an attacker fast as well.
As of 2019, every possible 8-character NTLM password hash can be enumerated by modern hardware in about 2.5 hours. It’s even faster if you use rainbow tables, which exist for all 8 and 9-character passwords.
NTLM v2
A number of the NTLM v1 weaknesses are corrected in v2:
- The challenge is a variable-length challenge.
- HMAC-MD5 is used instead of DES. It’s slower, so brute force isn’t a practical option… at least until quantum computers become available!
NTLM remains vulnerable to pass the hash attacks, in addition to not supporting modern encryption algorithms (AES, SHA-256).
Decommissioning NTLM and LANMan
Now that it’s clear why NTLM is a terrible modern choice for authentication, let’s sort out how to get rid of it. Many older devices may only support NTLM, so we need to identify any devices currently using it.
Audit
First, enable NTLM auditing on your Domain Controllers. This will create Event ID 4624 in the Security Event log. This event will note which authentication method was used: KERBEROS or NTLM. If it’s NTLM, a subfield will tell whether it’s LM, V1 or V2.
I created a GPO for my DCs and set these values under Computer Configuration\Windows Settings\Security Settings\Local Policies\Security Options:
Network Security: Restrict NTLM: Audit NTLM authentication in this domain to Enable all
Network security: Restrict NTLM: Audit Incoming NTLM Traffic to Enable auditing for all accounts
Network security: Restrict NTLM: Outgoing NTLM traffic to remote servers to Audit all
Now I have Event ID 4624 showing up in my logs. I want to find if there’s any NTLM v1 or LM traffic. Let’s parse this with with a custom XML filter for all records matching Event ID 4624 that don’t contain ‘NTLM v2’, ‘Kerberos’ or ‘-’ authentication types.
NOTE: This is the relevant part of my code for the filtering. The full script does some other things like emailing me a report, which is why there are other functions and variables referenced:
foreach ($domaincontroller in $domaincontrollers) {
Clear-Variable -Name eventlog
$query = @"
<QueryList>
<Query Id="0">
<Select Path="Security">
*[System[(EventID='4624')]]
</Select>
<Suppress Path="Security">
*[EventData[Data[@Name='AuthenticationPackageName'] and (Data='NTLM v2')]] or
*[EventData[Data[@Name='AuthenticationPackageName'] and (Data='Kerberos')]] or
*[EventData[Data[@Name='AuthenticationPackageName'] and (Data='-')]]
</Suppress>
</Query>
</QueryList>
"@
$eventlog = Get-WinEvent -FilterXml $query
$MyReport += Get-CustomHeader "1" "NTLMv1 Events on domain controller $domaincontroller"
$MyReport += Get-HtmlTable ($eventlog | Where-Object { $_.ID -eq "4624" } | Select-Object TimeCreated, Message)
$MyReport += Get-CustomHeaderClose
$MyReport += Get-CustomHeader0Close
$MyReport += Get-CustomHTMLClose
}
Good!
The only relevant entries I found were from a server that I upgraded 3 weeks ago, specifically because it was using NTLM for an obsolete application. After tossing on a supported OS and upgrading to the current application version, NTLMv1 authentication from this server stopped.
Block
MS exposes a GPO value to control the NTLM authentication methods available on the domain. Computer Configuration\Windows Settings\Security Settings\Local Policies\Security Options\Network security: LAN Manager authentication level will enforce these behaviours:
Setting | Description | Registry security level |
---|---|---|
Send LM & NTLM responses | Client devices use LM and NTLM authentication, and they never use NTLMv2 session security. Domain controllers accept LM, NTLM, and NTLMv2 authentication. | 0 |
Send LM & NTLM – use NTLMv2 session security if negotiated | Client devices use LM and NTLM authentication, and they use NTLMv2 session security if the server supports it. Domain controllers accept LM, NTLM, and NTLMv2 authentication. | 1 |
Send NTLM response only | Client devices use NTLMv1 authentication, and they use NTLMv2 session security if the server supports it. Domain controllers accept LM, NTLM, and NTLMv2 authentication. | 2 |
Send NTLMv2 response only | Client devices use NTLMv2 authentication, and they use NTLMv2 session security if the server supports it. Domain controllers accept LM, NTLM, and NTLMv2 authentication. | 3 |
Send NTLMv2 response only. Refuse LM | Client devices use NTLMv2 authentication, and they use NTLMv2 session security if the server supports it. Domain controllers refuse to accept LM authentication, and they will accept only NTLM and NTLMv2 authentication. | 4 |
Send NTLMv2 response only. Refuse LM & NTLM | Client devices use NTLMv2 authentication, and they use NTLMv2 session security if the server supports it. Domain controllers refuse to accept LM and NTLM authentication, and they will accept only NTLMv2 authentication. | 5 |
Obviously, 0 is the most insecure setting, but the most compatible. If your domain ever had a Domain Level lower than Windows Server 2008, 0 is probably what you’ll be using. Since Windows Server 2008, the default has been 3.
I’d previously changed our domain from 0 to 2, but now that our last NTLMv1 application is gone, I’ve set this to 3. We’re headed full speed into the future! 2008.