Kerberos and NTLM
How Windows domains prove who you are: the Kerberos ticket exchange with the key distribution center, service principal names, time synchronization, delegation, and the older NTLM protocol that is being phased out.
Why Kerberos
Kerberos is a network authentication protocol, version 5 of which is defined in RFC 4120, in which a trusted third party issues encrypted, time-limited tickets that let a user prove their identity to services without ever sending a password over the network. Active Directory has used it as its default authentication protocol since Windows 2000; Linux and macOS speak it too, and the same protocol runs in MIT Kerberos and in FreeIPA (see Linux and Identity).
Kerberos was designed around three goals:
- No passwords on the wire. The password is turned into a key on the client, and only things encrypted with that key travel. Someone capturing traffic does not get the password.
- Sign in once. After the first exchange, the client gets access to many services without asking the user again: the single sign-on of a Windows domain.
- Mutual authentication. The client can verify that it talks to the real service, not an impostor, because only the real service can decrypt its ticket.
The actors
A Kerberos exchange has three parties: the client (a user or computer), the service it wants to use (a file server, a web application, a database), and the key distribution center (KDC), the trusted service that knows the long-term keys of all accounts in a realm and issues tickets with them. The KDC has two parts: the authentication service (AS), which checks who the user is, and the ticket-granting service (TGS), which hands out tickets for individual services.
In Active Directory, every
domain controller
runs a KDC, listening on port 88; clients find one through DNS (see
DNS and Active Directory). The Kerberos realm is the domain name in capitals,
AD.EXAMPLE.COM. Every account's long-term key is
derived from its password; the KDC itself uses the key of a special
account, krbtgt. Whoever obtains the krbtgt key can
forge tickets for anyone (a "golden ticket", MITRE ATT&CK
T1558.001), which is why DCs are the most protected systems in a
domain and why incident response after a domain compromise includes
resetting the krbtgt password twice. Attacks and their detection are
covered on
Attacks on Identity.
The Kerberos exchange step by step
Lucía, a billing clerk, signs in to her laptop in the morning and
then opens \\fs01\billing. Behind the scenes, three
exchanges take place:
1–2: Getting a ticket-granting ticket
The client sends an AS-REQ to the authentication service. With Kerberos preauthentication, the client includes the current time encrypted with the key derived from the user's password, so the KDC can verify that the requester knows the password before it returns anything encrypted with that key. Preauthentication is on by default in AD. An account with the "Do not require Kerberos preauthentication" flag lets anyone request a reply for it and try to crack the password offline (AS-REP roasting, T1558.004). Find such accounts and remove the flag:
Get-ADUser -Filter 'DoesNotRequirePreAuth -eq $true' | Select-Object SamAccountName
If the timestamp checks out, the KDC answers with an AS-REP containing a ticket-granting ticket (TGT): a ticket for the ticket-granting service itself, encrypted with the krbtgt key, which proves to the KDC that the user authenticated and is used to request service tickets without the password. The client cannot read the TGT; it only stores it. The reply also contains a session key, encrypted with the user's key, that the client uses in the next step. From here on, the password is no longer needed.
3–4: Getting a service ticket
When Lucía opens \\fs01\billing, the client sends a
TGS-REQ: the TGT, an authenticator (a
fresh timestamp encrypted with the session key, which proves the TGT
is not replayed) and the name of the service it wants,
cifs/fs01.ad.example.com. The KDC looks up which
account has that service principal name and returns a
TGS-REP
with a
service ticket: a ticket for
one specific service, encrypted with the key of the account that
runs the service, which carries the user's identity and group
memberships and a session key for client and service.
In AD, the group memberships travel in a Microsoft extension inside the ticket, the Privilege Attribute Certificate (PAC). That is why a new group membership needs new tickets: the old ones still carry the old list (see when a membership change takes effect).
5–6: Using the service
The client sends the service ticket and a new authenticator to the file server in an AP-REQ. The file server decrypts the ticket with its own key; if that works, the ticket must have come from the KDC. It reads the user's identity and groups from the ticket and checks the authenticator's timestamp. No call to a DC is needed, which makes Kerberos fast and scalable. If the client asks for mutual authentication, the service proves its identity in an AP-REP encrypted with the session key, which only the real service could have read from the ticket.
The flip side: because a service ticket is encrypted with the
service account's key, any authenticated user can request one and
try to guess the password offline. Against an account with a long
random password, such as a computer account or a
group Managed Service Account, that is hopeless; against svc-sql with a password
from 2014 it is not. That is Kerberoasting (T1558.003).
Service principal names
A
service principal name (SPN)
is the unique name of a service instance in Kerberos, in the form
serviceclass/host[:port], registered on the account
that runs the service so the KDC knows which key to encrypt service
tickets with. Examples:
-
HOST/pc-bil-014.ad.example.com, registered automatically on each computer account and covering built-in services such as file sharing (cifs); -
HTTP/intranet.ad.example.comfor a web application whose application pool runs as a service account; -
MSSQLSvc/sql01.ad.example.com:1433for a SQL Server instance.
Each SPN must be registered on exactly one account
in the forest. The setspn tool manages them:
setspn -L AD\svc-intranet # list SPNs of an account
setspn -Q HTTP/intranet.ad.example.com # which account has this SPN?
setspn -S HTTP/intranet.ad.example.com AD\svc-intranet # add, after checking for duplicates
setspn -X -F # find duplicates in the forest
Two SPN problems cause most Kerberos tickets that reach the service desk:
-
Duplicate SPN. Two accounts claim the same name,
typically after a service was moved from one account to another
and the old SPN was left behind. The KDC cannot know whose key to
use, logs an error on the DC, and the request fails; many clients
then quietly fall back to NTLM. Always add SPNs with
setspn -S, never-A, which skips the duplicate check. -
SPN on the wrong account. The KDC encrypts the
ticket for the account that has the SPN, but the service runs
under another account and cannot decrypt it. The client sees
KRB_AP_ERR_MODIFIEDerrors, often after someone changed an application pool from a service account to a built-in identity.
Time, clock skew and ticket lifetimes
Authenticators and tickets carry timestamps, and services remember recently seen authenticators, so a captured message cannot be replayed later. That only works if clocks agree. Clock skew is the difference between the clocks of two systems; Kerberos rejects requests whose timestamps differ from the receiver's clock by more than an allowed maximum, which is 5 minutes by default in Windows domains. Time zones do not matter: Kerberos compares instants in UTC, so a laptop set to the wrong time zone but the correct UTC time is fine.
# Would a Kerberos service accept these requests? Check the clock skew.
from datetime import datetime, timedelta, timezone
MAX_SKEW = timedelta(minutes=5) # the Windows default
server_time = datetime(2026, 10, 1, 9, 0, 0, tzinfo=timezone.utc)
# Timestamps from the authenticators that clients sent (ISO 8601).
requests = [
("PC-BIL-014", "2026-10-01T09:01:30+00:00"),
("PC-WS-031", "2026-10-01T08:54:59+00:00"),
("LAB-VM-07", "2026-10-01T11:00:10+02:00"), # local time, with offset
("PC-NOC-02", "2026-10-01T09:05:00+00:00"),
("SRV-OLD-01", "2026-10-01T09:07:45+00:00"),
]
for host, stamp in requests:
skew = datetime.fromisoformat(stamp) - server_time
seconds = int(skew.total_seconds())
verdict = "accept" if abs(skew) <= MAX_SKEW else "reject (KRB_AP_ERR_SKEW)"
print(f"{host:<11}{seconds:+5d} s {verdict}")
PC-BIL-014 +90 s accept PC-WS-031 -301 s reject (KRB_AP_ERR_SKEW) LAB-VM-07 +10 s accept PC-NOC-02 +300 s accept SRV-OLD-01 +465 s reject (KRB_AP_ERR_SKEW)
LAB-VM-07 shows 11:00 on its clock but is only 10 seconds off, because its offset says it is two hours ahead of UTC. PC-WS-031 is rejected for being one second too far behind: the limit is sharp.
Windows keeps clocks in line through a hierarchy: members
synchronize with a DC, DCs with the PDC emulator of their domain,
and the PDC emulator of the forest root domain with a reliable
external source over NTP (see
NTP).
w32tm /query /status shows where a machine gets its
time; w32tm /resync forces a synchronization. A virtual
machine that takes its time from the hypervisor host while also
syncing with the domain is a classic source of drift.
Ticket lifetimes and klist
Tickets expire. In the Default Domain Policy, the maximum lifetime
of a user's TGT is 10 hours, which covers a working day; a ticket
can be renewed without the password up to a maximum renewal period
set in the same policy. When it runs out, Windows gets a new one
using the cached credentials. klist shows the tickets
of the current session:
klist
Current LogonId is 0:0x3e7a1
Cached Tickets: (2)
#0> Client: lromero @ AD.EXAMPLE.COM
Server: krbtgt/AD.EXAMPLE.COM @ AD.EXAMPLE.COM
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
Start Time: 10/1/2026 8:15:03 (local)
End Time: 10/1/2026 18:15:03 (local)
Renew Time: 10/8/2026 8:15:03 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Kdc Called: DC01.ad.example.com
#1> Client: lromero @ AD.EXAMPLE.COM
Server: cifs/fs01.ad.example.com @ AD.EXAMPLE.COM
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40a10000 -> forwardable renewable pre_authent name_canonicalize
Start Time: 10/1/2026 8:16:40 (local)
End Time: 10/1/2026 18:15:03 (local)
Renew Time: 10/8/2026 8:15:03 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Kdc Called: DC01.ad.example.com
Ticket #0 is the TGT (server krbtgt/…, flag
initial), ticket #1 the service ticket for the file
server. klist purge deletes the cached tickets, so the
next access requests fresh ones, which is useful after an SPN fix.
No ticket for a service at all, while access works, usually means
the connection used NTLM.
Delegation
Sometimes a service must act as the user toward another service: a web application that reads a report from SQL Server with the permissions of the person who opened the page. Kerberos delegation is the Active Directory feature that lets a service obtain Kerberos tickets to other services on behalf of a user who authenticated to it. There are three kinds, from oldest and riskiest to newest:
| Kind | How it works | Risk |
|---|---|---|
| Unconstrained | The user's TGT is forwarded to the service, which can then request tickets to any service as that user. | High: whoever controls that server can reuse the TGTs of everyone who connects, including administrators. DCs have it by design; other servers should not. |
| Constrained | The service account gets a list of SPNs it may delegate to; set by a domain administrator on the front-end account. | Limited to the listed services, but configure it carefully. |
| Resource-based constrained | The back-end resource lists which front-end accounts may delegate to it; its owner decides. | Anyone with write access to that setting on a computer object can abuse it; review who can modify computer objects. |
Defenses: find and remove unconstrained delegation outside the DCs, mark privileged accounts "Account is sensitive and cannot be delegated" or put them in the Protected Users group, and review delegation settings as part of regular access reviews.
# Computers trusted for unconstrained delegation (expect only DCs here)
Get-ADComputer -Filter 'TrustedForDelegation -eq $true' | Select-Object Name
Encryption types: AES, not RC4
Tickets and session keys can be encrypted with several algorithms. Current Windows uses AES (AES256 and AES128 with SHA-1 based integrity, from RFC 3962). The older RC4-HMAC type uses the account's NT hash, the unsalted hash of its password, as the key, which makes offline cracking of service tickets much faster and links Kerberos weaknesses to NTLM ones. See symmetric encryption for the algorithms themselves.
Microsoft has been removing RC4 from Kerberos in phases, tracked as CVE-2026-20833:
- 13 January 2026: updates added audit events and a registry setting to test the new behavior early.
-
14 April 2026: enforcement on by default. Domain
controllers issue service tickets with AES only for accounts
without an explicit
msDS-SupportedEncryptionTypesvalue; rollback was still possible. - From July 2026: the rollback setting is removed. RC4 is used only where it is explicitly configured on an account.
To find what still uses RC4, look at the DC security events 4768
(TGT requested) and 4769 (service ticket requested): the field
"Ticket Encryption Type" shows 0x12 for AES256 and
0x17 for RC4. Old appliances, Java applications with
fixed keytabs and accounts whose password was last set before AES
keys existed are the usual suspects; resetting such an account's
password generates its AES keys.
NTLM
NTLM (NT LAN Manager) is Microsoft's older challenge-response authentication protocol, in which the client proves knowledge of the password by computing a response to a random challenge from the server using the password's hash, without a ticket or a trusted third party in the exchange. It still exists because Kerberos needs things NTLM does not: a reachable DC, a name with an SPN, and a domain. Workgroup computers, local accounts, connections by IP address and old applications fall back to it.
The exchange takes three messages:
- NEGOTIATE: the client says it wants to use NTLM.
- CHALLENGE: the server sends a random number.
- AUTHENTICATE: the client returns a response computed from the challenge and the user's NT hash. For a domain account, the server passes it to a DC, which checks it.
Why NTLM is weaker
- No mutual authentication. The client never verifies the server, so it can be tricked into authenticating to an attacker.
- Relay. An attacker in the middle can forward a challenge and the victim's response to another server and be signed in there as the victim (an adversary-in-the-middle technique, T1557). SMB signing, LDAP signing and channel binding (see Directory Services and LDAP) and Extended Protection for Authentication on web servers break relaying.
- The hash is the password. The response is computed from the NT hash, not from the password itself, so an attacker who steals a hash from memory can authenticate without knowing the password (pass-the-hash, T1550.002).
- Weak old versions. NTLMv1 and LAN Manager use cryptography that can be broken quickly.
Deprecation and removal
In June 2024 Microsoft marked all NTLM versions (LAN Manager, NTLMv1 and NTLMv2) as deprecated: they still work, but are no longer developed, and applications should call the Negotiate package, which prefers Kerberos. NTLMv1 is removed starting with Windows 11 24H2 and Windows Server 2025. Early in 2026 Microsoft published a roadmap toward disabling network NTLM by default, which as reported describes three phases: better NTLM auditing (in Windows 11 24H2 and Server 2025), then features that let Kerberos work in cases that used to need NTLM, such as IAKerb and a local KDC (planned for the second half of 2026), and finally a future Windows release in which network NTLM is off by default but can be turned back on by policy. Check Microsoft's current documentation before planning around specific dates.
Audit before you block
Turning NTLM off without knowing who uses it breaks printers, scanners and line-of-business applications on a Monday morning. Audit first:
- Enable the Group Policy security options Network security: Restrict NTLM: Audit NTLM authentication in this domain (on DCs) and Audit Incoming NTLM Traffic (on servers); see Group Policy. Events appear in Applications and Services Logs › Microsoft › Windows › NTLM › Operational.
- In the Security log, logon event 4624 shows "Authentication Package: NTLM" and the NTLM version used, which is how you find remaining NTLMv1.
- Fix the causes (add the missing SPN, use names instead of IP addresses, update the application), then restrict NTLM with exceptions for what cannot be fixed yet, and shrink the exception list over time.
Common mistakes
-
Ignoring time. A server whose clock drifted 6
minutes rejects every Kerberos request. Check
w32tm /query /statusearly in any "sudden sign-in failures on one server" ticket. - Moving a service without moving its SPN, which leaves duplicates or an SPN on the wrong account.
- Service accounts with weak passwords and RC4. They are exactly what Kerberoasting targets; use gMSAs and AES.
- Unconstrained delegation "to make it work". Use constrained or resource-based delegation for the specific services instead.
- Disabling NTLM without auditing. Measure first; then restrict with exceptions.