Skip to content

Audit and restrict NTLM in Active Directory

A step-by-step NTLM reduction plan: audit with events 8001-8004, fix the causes, build an exception list, remove NTLMv1 and set LmCompatibilityLevel 5.

Florian Amette7 min read

Every NTLM authentication in your domain is a potential relay, a potential hash to crack offline and a credential that can be passed without knowing the password. LDAP and SMB signing close specific relay targets, but the real fix is to stop using NTLM where Kerberos works, and to refuse it where nothing legitimate needs it. Microsoft deprecated NTLM in 2024, and Windows 11 24H2 and Windows Server 2025 no longer include NTLMv1, which makes this the right time to measure and shrink what remains.

This guide expands the short "Restrict NTLM" section of the NTLM and legacy protocols pillar into a full programme: turning on the right audit settings, reading events 8001 to 8004, fixing the common causes, building an exception list that stays small, and removing NTLMv1 for good.

The Restrict NTLM policies

All Restrict NTLM settings are Security Options, not administrative templates:

Text
Computer Configuration > Policies > Windows Settings > Security Settings >
  Local Policies > Security Options > Network security: Restrict NTLM: ...
SettingApplies onAudit valueEnforce value
Audit NTLM authentication in this domainDomain controllersEnable alln/a
NTLM authentication in this domainDomain controllersn/aDeny all (or a narrower deny)
Add server exceptions in this domainDomain controllersn/aServers allowed to use NTLM
Audit Incoming NTLM TrafficMember servers and clientsEnable auditing for all accountsn/a
Incoming NTLM trafficMember servers and clientsn/aDeny all accounts
Outgoing NTLM traffic to remote serversClients and serversAudit allDeny all
Add remote server exceptions for NTLM authenticationClients and serversn/aServers the client may still use NTLM with

The events go to Applications and Services Logs > Microsoft > Windows > NTLM > Operational:

EventLogged onMeaning
8001ClientOutgoing NTLM that the outgoing policy would block
8002ServerIncoming NTLM (including local accounts) that the incoming policy would block
8003Member serverIncoming NTLM with a domain account that the domain policy would block
8004Domain controllerNTLM authentication passed through to this DC: user, workstation and the server (secure channel name) that requested it

When you move a setting from audit to deny, the same channel logs the corresponding block events.

Step 1: Measure the volume

Turn on auditing everywhere through a GPO that only contains audit values. Audit mode changes nothing functionally.

  • On the Domain Controllers OU: Audit NTLM authentication in this domain = Enable all, Audit Incoming NTLM Traffic = Enable auditing for all accounts.
  • On all other computers: Audit Incoming NTLM Traffic = Enable auditing for all accounts, Outgoing NTLM traffic to remote servers = Audit all.

Increase the NTLM/Operational log size (8004 is chatty on busy DCs) and forward it centrally with Windows Event Forwarding. Also collect Security events 4776 (credential validation) on DCs and 4624 everywhere: 4624 records the LmPackageName field, which says whether a logon used NTLM V1, NTLM V2 or LM.

Step 2: Find NTLMv1 first

NTLMv1 responses can be cracked to the account's NT hash quickly, so it goes before anything else. Look for it on DCs and servers:

PowerShell
$xpath = "*[System[EventID=4624] and EventData[Data[@Name='AuthenticationPackageName']='NTLM'] and EventData[Data[@Name='LmPackageName']!='NTLM V2']]"
$dcs = (Get-ADDomainController -Filter *).HostName
foreach ($dc in $dcs) {
    Get-WinEvent -ComputerName $dc -LogName Security -FilterXPath $xpath -MaxEvents 2000 -ErrorAction SilentlyContinue |
        ForEach-Object {
            $x = [xml]$_.ToXml(); $d = @{}
            $x.Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_.'#text' }
            [PSCustomObject]@{
                DC = $dc; User = "$($d.TargetDomainName)\$($d.TargetUserName)"
                Workstation = $d.WorkstationName; IP = $d.IpAddress; Package = $d.LmPackageName
            }
        }
} | Group-Object Workstation, User, Package | Sort-Object Count -Descending | Select-Object Count, Name

Filter out anonymous logons (LmPackageName = -) when you review. Genuine NTLMv1 usually comes from old non-Windows devices, very old Windows systems, or machines with a local policy that sets LmCompatibilityLevel below 3.

Step 3: Classify the NTLM you see

Summarise 8004 on DCs by the server that asked for authentication and the client workstation:

PowerShell
foreach ($dc in $dcs) {
    Get-WinEvent -ComputerName $dc -LogName 'Microsoft-Windows-NTLM/Operational' `
        -FilterXPath '*[System[EventID=8004]]' -MaxEvents 20000 -ErrorAction SilentlyContinue |
        ForEach-Object {
            $x = [xml]$_.ToXml(); $d = @{}
            $x.Event.EventData.Data | ForEach-Object { $d[$_.Name] = $_.'#text' }
            [PSCustomObject]@{ Server = $d.SChannelName; User = $d.UserName; Client = $d.WorkstationName }
        }
} | Group-Object Server | Sort-Object Count -Descending | Select-Object Count, Name -First 50

Field names in the event XML can vary slightly between Windows versions; check one event with $_.ToXml() and adjust. Then assign each server/client pair to a cause:

  • Access by IP address. Kerberos needs an SPN, and clients do not try IP-based SPNs by default. Change the path, mapping or application config to use the DNS name. Where an IP is unavoidable, Windows 10 and Server 2016 onward can use Kerberos with an IP SPN registered on the target account and the client TryIPSPN registry value enabled under HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Kerberos\Parameters.
  • Missing or duplicate SPNs, CNAMEs and load balancer names. Register the alias as an SPN on the service account (setspn -S), and use setspn -X to find duplicates that make the KDC fail and the client fall back.
  • Local accounts. Remote use of local accounts is always NTLM. With Windows LAPS deployed, most of this is admins or tools using local credentials remotely; move them to domain accounts in the right tier.
  • Non-domain and workgroup devices, including appliances. Decide per device: join, move to Kerberos (many Linux and appliance stacks support it with a keytab), or accept as an exception.
  • Applications calling NTLM explicitly instead of Negotiate. These need a vendor fix or an exception.
  • Cross-forest without a trust, or through a trust where name suffix routing is broken. Fix routing or accept an exception.

Step 4: Enforce in rings

Harden NTLM that remains

Before blocking, raise the bar for the NTLM you still allow. These can go domain-wide once NTLMv1 is gone:

Text
Network security: LAN Manager authentication level
  = Send NTLMv2 response only. Refuse LM & NTLM          (LmCompatibilityLevel = 5)
Network security: Minimum session security for NTLM SSP based (including secure RPC) clients
  = Require NTLMv2 session security, Require 128-bit encryption
Network security: Minimum session security for NTLM SSP based (including secure RPC) servers
  = Require NTLMv2 session security, Require 128-bit encryption
Network security: Do not store LAN Manager hash value on next password change = Enabled

LmCompatibilityLevel lives in HKLM\SYSTEM\CurrentControlSet\Control\Lsa; the two minimum session security values are NTLMMinClientSec and NTLMMinServerSec (537395200 for both options) under Lsa\MSV1_0. Apply level 5 to DCs first, since they are the ones validating domain accounts, then to everything else.

Block NTLM for the most sensitive identities and hosts

  • Put Tier 0 accounts in Protected Users; members cannot authenticate with NTLM at all.
  • Deny Outgoing NTLM traffic to remote servers on privileged access workstations, so admin credentials never leave them as NTLM.
  • Deny Incoming NTLM traffic on Tier 0 servers that show no legitimate NTLM in the audit data.

Deny NTLM in the domain with exceptions

Once 8004 volume is down to known, accepted sources, set NTLM authentication in this domain on DCs to a deny value and list the remaining servers under Add server exceptions in this domain (one server name per line, wildcards allowed). Start with "Deny for domain accounts to domain servers", which leaves NTLM from non-domain servers alone, then tighten. Each exception needs an owner and a review date; an exception list that only grows is not a control.

Verify

  • 8004 volume on DCs trends to zero outside the exception servers; block events appear only for sources you intended to block.
  • The 4624 NTLMv1 query from step 2 returns nothing.
  • Registry checks on a sample of hosts:
PowerShell
Invoke-Command -ComputerName $dcs -ScriptBlock {
    [PSCustomObject]@{
        Host  = $env:COMPUTERNAME
        LmCompat = (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa').LmCompatibilityLevel
        MinSrvSec = (Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0').NTLMMinServerSec
    }
}
  • A test with a Protected Users account against an IP address path should fail, while the same path by DNS name succeeds with Kerberos (klist shows a ticket for the service).

What it breaks

  • LmCompatibilityLevel 5 on DCs breaks anything still sending LM or NTLMv1 responses: old copiers and NAS devices, legacy Unix SMB clients, and systems with a hard-coded low level.
  • Minimum session security breaks old clients and appliances that cannot negotiate NTLMv2 session security or 128-bit encryption.
  • Denying NTLM in the domain breaks access by IP, local-account remote administration, workgroup devices, some VPN and Wi-Fi setups that validate users through NTLM-based protocols, and applications hard-coded to NTLM, unless they are on the exception list.
  • Denying outgoing NTLM on PAWs breaks admin tools that connect to devices by IP or to non-domain appliances; admins need a separate path for those.
  • Protected Users members lose NTLM entirely, so any service they use only through NTLM stops working for them.

Related reading: the NTLM & Legacy Protocols topic, NTLM relay and pass-the-hash for what NTLM exposure enables, and Kerberos hardening because every NTLM flow you remove becomes a Kerberos flow that should use AES.

Frequently asked questions

Why do clients use NTLM when Kerberos is available?

The most common reasons are connecting by IP address instead of name, a missing or duplicated SPN, a name that resolves through a CNAME or load balancer without a matching SPN, local accounts, workgroup or non-domain devices, cross-forest access without a trust, and applications that call the NTLM package directly. Each cause has a different fix, so classify your 8004 events by cause before deciding what goes on the exception list.

Does LmCompatibilityLevel 5 on clients alone disable NTLMv1?

No. The client setting controls what a machine sends. The setting that refuses NTLMv1 and LM responses is the one on the server doing the validation, which for domain accounts means the domain controllers. Set level 5 on DCs to reject NTLMv1 for domain accounts, and on member servers to reject it for their local accounts. Setting it everywhere through one GPO is simplest.

Is it realistic to block NTLM completely?

For most organisations, not domain-wide in one step. It is realistic to block NTLM for Tier 0 accounts and systems, to deny outgoing NTLM from privileged access workstations, and to deny NTLM in the domain with a short, reviewed exception list. Microsoft has deprecated NTLM and is adding Kerberos features to close the remaining gaps, so shrinking usage now makes the eventual switch-off far easier.

Audit and restrict NTLM in Active Directory

Related guides

Kerberos & Authentication

Disable RC4 in Kerberos: audit, fix and enforce AES

Remove RC4 from Kerberos safely: audit 4768/4769, fix accounts without AES keys, set msDS-SupportedEncryptionTypes and DefaultDomainSupportedEncTypes, enforce.

Intermediate
NTLM & Legacy Protocols

Stop NTLM relay: LDAP, SMB signing and LLMNR

Harden LDAP signing, LDAP channel binding, SMB signing, and disable LLMNR/NBT-NS to shut down NTLM relay paths against domain controllers.

Foundation