Revisiting Constrained Delegation
Constrained Delegation was introduced in Windows Server 2003 as an improved and more secure version of Unconstrained Delegation. Constrained Delegation allows admins to limit the services to which an impersonated account can connect to. It is using two Kerberos extensions to allow impersonation to only specific services.
- S4U2Self: An service can request a forwardable Service Ticket on behalf of any non-protected user.
- S4U2Proxy: An account is allowed to request a Service Ticket to any services that is specified in the msDS-AllowedToDelegateTo attribute.
Example
Here we can see an example, whereby Server001$ has the ability to act on behalf of any user to the CIFS service on the Server002$ host. This is an example of how ”Constrained” Delegation looks like.

Enumerating accounts with Constrained Delegation
Once we configure a user or computer to be configured for Constrained Delegation. There is an LDAP attribute that will disclose this information and is known as ‘msDS-AllowedToDelegateTo’.

Exploiting Constrained Delegation
Since we know that in our example. Server001$ has the rights to delegate to the CIFS service on the Server002$ host. We will need to obtain the NT hash of the Server001$ account, so we can start request a Service Ticket to access the CIFS service on the targeted machine.
In order to obtain the NT hash of the Server001$, we will need to dump the credentials from the LSASS process memory. We will be using the the sekurlsa::logonPasswords module of Mimikatz.

The second thing we need to do is create a Service Ticket for the CIFS service on behalf of any user, that we like to impersonate. In order to access the CIFS service on the Server002$ host.
During this example, we will be impersonating the svc_local account to access the CIFS service on Server002$. This account is a local admin on the Server002$ host.
Rubeus.exe s4u /user:Server001$ /rc4:8d47af90e791ee32dbae97ba9b2212b5 /domain:fabrikam.com /impersonateuser:svc_local /msdsspn:"cifs/Server002" /ptt
Result:
At the result, we can see that we have now requested a Service Ticket on behalf of the svc_local account for the CIFS service.

We can now use something like PsExec to connect against the Server002$ host.

Let’s now impersonate other accounts, since according to the theory. We should be able to impersonate any account that we want, right?
During this example, we are impersonating a Domain Admin to access the CIFS service on Server002$.
Rubeus.exe s4u /user:Server001$ /rc4:8d47af90e791ee32dbae97ba9b2212b5 /domain:fabrikam.com /impersonateuser:Moreno /msdsspn:"cifs/Server002" /ptt
Result:
At the result, we can see that we have requested a Service Ticket on behalf of Moreno to access the CIFS service on Server002$ host.

We can see a Kerberos Service Ticket of the user Moreno for the CIFS service.

We can now PsExec against the Server002$ host, since Moreno is a local admin on the Server002$ host.

Compromising Domain via Constrained Delegation
Servers with Unconstrained Delegation can lead to a full domain compromise, but what about servers with Constrained Delegation? Any user or computer that is allowed to delegate to a service (i.e. CIFS, HTTP, LDAP) on a Domain Controller can potentially compromise an entire domain as well.
Here we can see that Server001$ is allowed to delegate to the LDAP service on MDEDC2016$, which is in this case. A Domain Controller.

The first step is to obtain the NT hash of the Server001$ host. We will be using the sekurlsa::logonPasswords module of Mimikatz to achieve this.

The second step is to request a Service Ticket on behalf of any user to access the LDAP service on the Domain Controller. The user Testing is a Domain Admin in this example.
Rubeus.exe s4u /user:Server001$ /rc4:8d47af90e791ee32dbae97ba9b2212b5 /domain:fabrikam.com /impersonateuser:Testing /msdsspn:"ldap/MDEDC2016.fabrikam.com" /dc:MDEDC2016.fabrikam.com /ptt
We have now requested a Service Ticket for the user Testing to access the LDAP service on the MDEDC2016$ host.

Result:
At the final result, we can see that we obtained a Service Ticket on behalf of the user Testing to access the LDAP service on the MDEDC2016$ host.

We have now a Service Ticket of a Domain Admin that can access the LDAP service, which is enough to execute a DCSync attack.

Other Exploitable Service
We have demonstrated that we could exploit the CIFS & LDAP service. However, there are other services that can be exploited as well, which includes HTTP. There are for sure more services, but we won’t cover all of them.

The HTTP service is used for PowerShell Remoting.

We are now going to request a Service Ticket on behalf of the user Moreno for the HTTP service on the Server002$ host.
Rubeus.exe s4u /user:Server001$ /rc4:8d47af90e791ee32dbae97ba9b2212b5 /domain:fabrikam.com /impersonateuser:Moreno /msdsspn:"http/Server002" /ptt
Result:
At the result, we can see that have requested a Service Ticket for the HTTP service.

The final step is to use PowerShell Remoting to connect against the Server002$ host.
Enter-PSSession -ComputerName Server002

Protocol transition
Once a service is configured for Constrained Delegation with protocol transition. It can obtain a Service Ticket on behalf of any non-protected user through the S4U2Self and S4U2Proxy extensions. This allows clients to authenticate with any protocol and have the service delegate those credentials to the subsequent host.

Here we are requesting a Service Ticket on behalf of the user Moreno for the HTTP service to the Server002$ host.
Rubeus.exe s4u /user:Server001$ /rc4:8d47af90e791ee32dbae97ba9b2212b5 /domain:fabrikam.com /impersonateuser:Moreno /msdsspn:"http/Server002" /ptt
Result:
At the result, we can see that we have requested a Service Ticket of Moreno for HTTP service on the Server002$ host. This Kerberos ticket has an forwardable flag. An account can use this special requested ticket to request a service ticket to any service that is specified in the account’s msDS-AllowedToDelegateTo attribute.

Non Protocol transition
There are scenarios where users and computers have Constrained Delegation, but without protocol transition. This means that a server in this case, cannot obtain a Service Ticket for a non-protected user to itself. There may be configurations out there without protocol transition, but from my own experience. I don’t see this much in production environments.

In order to test this out, we are trying to request a Service Ticket on behalf of the user Moreno to access the HTTP service on the Server002$ host.
Rubeus.exe s4u /user:Server001$ /rc4:8d47af90e791ee32dbae97ba9b2212b5 /domain:fabrikam.com /impersonateuser:Moreno /msdsspn:"http/Server002" /ptt
Result:
At the result, we can see different things that caught our attention. There is no service (i.e. HTTP, CIFS, HOST) being specified for the Server and we cannot see the forwardable flag at the Kerberos ticket. This does not mean that the server is ”secure” by default.

Mitigation
We have mentioned ‘non-protected’ users a couple of times, but when is a user considered to be ‘protected’? Well, there is an checkbox that we can enable. This checkbox will prevent that we can request a Service Ticket on behalf of an protected user to access a service.
- Enable the Account is sensitive and cannot be delegated flag on your Tier-0 accounts.

- Every user or computer that is allowed to delegate to any service of a Tier-0 resource (i.e. Domain Controllers, AAD Connect, ADFS) should be treated as a Tier-0 as well
Reference
- Understanding Kerberos Delegation in Windows Server Active Directory: https://petri.com/understanding-kerberos-delegation-in-windows-server-active-directory
- (KCD) Constrained: https://www.thehacker.recipes/ad/movement/kerberos/delegations/constrained
- Tools