Kerberos pre-authentication normally forces a client to prove it knows the password before the KDC answers. Accounts with the Do not require Kerberos preauthentication flag skip that proof, so the KDC returns an AS-REP encrypted with the account key. Detection has two halves: find the accounts that carry the flag, and alert on requests that use it.
Signals at a Glance
| Signal | Where | ATT&CK |
|---|---|---|
| TGT request with pre-authentication type 0 for a user account | DC Security 4768 | T1558.004 |
| RC4 (0x17) AS-REP returned to a non-server client | DC Security 4768 | T1558.004 |
| Do not require Kerberos preauthentication enabled on an account | DC Security 4738, 5136 | T1098 |
| Burst of 4768 requests for many usernames from one IP | DC Security 4768 | T1558.004 |
| Existing accounts with DONT_REQ_PREAUTH set | LDAP inventory | T1558.004 |
Detecting the Request
Event ID 4768 (a Kerberos authentication ticket was requested) carries a pre-authentication type. A value of 0 means no pre-authentication was supplied. A handful of legacy applications do this legitimately, so list them first, then alert on everything else:
title: Kerberos TGT Requested Without Pre-Authentication
status: experimental
logsource:
product: windows
service: security
detection:
selection:
EventID: 4768
PreAuthType: '0'
Status: '0x0'
filter_machine:
TargetUserName|endswith: '$'
filter_known:
TargetUserName:
- 'legacy_app_account' # tune/validate: your documented exceptions
condition: selection and not 1 of filter_*
level: high
# Burst variant: count distinct TargetUserName per IpAddress over 10 minutes.
Attackers who do not yet know which accounts are roastable will often spray a username list at the KDC. That shows up as many 4768 events, some failing with 0x6 (client not found), from one source:
SecurityEvent
| where EventID == 4768
| summarize users = dcount(TargetUserName), bad = countif(Status == "0x6"),
noPreauth = countif(PreAuthType == "0")
by IpAddress, bin(TimeGenerated, 10m)
| where users >= 15 or noPreauth >= 1
// tune/validate: exclude your vulnerability scanners and jump hosts.
Finding and Auditing the Flag
The flag is a user-account-control bit, so enabling it leaves a trail. Event ID 4738 (a user account was changed) shows the new account-control state, and 5136 records the attribute write if directory-service change auditing is on:
SecurityEvent | where EventID == 4738 | where UserAccountControl has "%%2096" // Don't Require Kerberos Preauthentication - Enabled | project TimeGenerated, Computer, TargetUserName, SubjectUserName, UserAccountControl // tune/validate: confirm the %%2096 token against a test change in your domain.
- Run a scheduled LDAP inventory for
userAccountControl:1.2.840.113556.1.4.803:=4194304and review every result; most should be empty. - Where the flag cannot be removed, give the account a 25-character or longer random password so a captured AS-REP is not crackable.
- Treat any change that enables the flag on a privileged account as a high-severity event.
Use the SigmaHQ and Elastic rules for Kerberos pre-authentication and account-control changes, the Splunk ESCU AS-REP analytics, and Microsoft’s guidance on Kerberos pre-authentication. Baseline your own environment — some UNIX and appliance integrations legitimately run without pre-authentication and must be documented as exceptions.
Build Detections That Fire
Mjolnir Security helps blue teams turn threat intelligence into high-fidelity detections across endpoint, network, identity and cloud telemetry.
- Detection Engineering We build and tune detections mapped to ATT&CK from your own telemetry.
- Threat Hunting as a Service Hypothesis-driven hunts for the behaviours on this page.
- 24/7 Incident Response Containment when a detection fires. Call +1 833 403 5875.
Stay ahead of emerging threats. Get notified when we publish new intelligence reports and advisories.
Subscribe to Alerts