shield-quarteredConstrained Delegation

Now I have to explain Constrained Delegation (I want to bloody die). At least this is one of the easier ones.

Configuration and Enumeration

Instead of the TRUSTED_FOR_DELEGATION flag, constrained delegation is configured via the msDS-AllowedToDelegateTo attribute on the computer object. This attribute contains a list of SPNs to which this computer is allowed to delegate.

We can enumerate these computers using ldapsearch:

beacon> ldapsearch (&(samAccountType=805306369)(msDS-AllowedToDelegateTo=*)) --attributes samAccountName,msDS-AllowedToDelegateTo

sAMAccountName: [FRONT_SERVER_1]$

msDS-AllowedToDelegateTo: cifs/[BACK_SERVER_1].[DOMAIN.COM], cifs/[BACK_SERVER_1

This result tells us that the server [FRONT_SERVER_1]$ can delegate authentication to the cifs service on [BACK_SERVER_1].


Constrained Delegation Scenarios

The exact flow depends on how the user authenticates to the front-end service.

1. "Kerberos Only" Scenario (S4U2proxy)

This is the default and simplest flow.

  1. The user authenticates to the front-end service (e.g., http/[FRONT_SERVER_1]$) using Kerberos and presents a service ticket.

  2. The front-end service caches this ticket.

  3. When it needs to access the back-end (e.g., cifs/[BACK_SERVER_1]), the front-end sends a TGS-REQ to the KDC. This request includes its own authentication and a copy of the user's service ticket.

  4. The KDC verifies that cifs/[BACK_SERVER_1] is in the msDS-AllowedToDelegateTo list of [FRONT_SERVER_1]$.

  5. If the check is successful, the KDC returns a service ticket for cifs/[BACK_SERVER_1] in the user's name.

  6. The front-end uses that ticket to access the back-end as the user.

This is S4U2proxy in action.

2. Scenario with Protocol Transition (S4U2self + S4U2proxy)

What happens if the user authenticates to the front-end using NTLM? The front-end server won't have a user service ticket to use in the S4U2proxy request.

This is where Protocol Transition comes into play.

This feature must be explicitly enabled by setting the TRUSTED_TO_AUTH_FOR_DELEGATION flag (decimal value 16777216) in the front-end computer's UserAccountControl attribute.

First, we look up the computer's UAC value:

Then, we verify if the flag is active with a bitwise AND operation (the default value for a computer is 4096).

Since it is True, protocol transition is enabled. The flow is now:

  1. The user authenticates to the front-end (e.g., with NTLM).

  2. The front-end, lacking a user ticket, performs an S4U2self request. It sends a TGS-REQ to the KDC asking for a ticket for itself ([FRONT_SERVER_1]$) but on behalf of the user ([ADMIN_USER], for example).

  3. The KDC returns a service ticket for [ADMIN_USER]@[FRONT_SERVER_1]$. This ticket is marked as "forwardable".

  4. The front-end now uses this forwardable ticket to perform the S4U2proxy request we saw earlier, asking for a ticket for the back-end (cifs/[BACK_SERVER_1]) as [ADMIN_USER].

  5. The KDC approves it, and the front-end accesses the back-end.


Attacking Constrained Delegation (S4U)

If an attacker compromises a server configured for constrained delegation, they can abuse this trust. The method varies depending on whether protocol transition is enabled.

Attack WITH Protocol Transition

This is the most powerful attack. Because protocol transition is enabled, the attacker can impersonate any user they want, including a Domain Administrator.

We only need a TGT for the compromised computer account. Rubeus can perform the S4U2self and S4U2proxy steps in a single s4u command:

  • /user: The principal configured for delegation.

  • /msdsspn: The target service we can delegate to.

  • /ticket: The TGT of the computer account we control.

  • /impersonateuser: The user we want to impersonate (anyone!).

Step 1: Rubeus performs S4U2self

Rubeus uses the TGT of [FRONT_SERVER_1]$ to request a ticket for itself on behalf of [ADMIN_USER].

This returned ticket is forwardable.

Step 2: Rubeus performs S4U2proxy

Rubeus automatically uses that forwardable ticket to request a ticket to the target SPN.

Step 3: Use the ticket

We now have a valid ticket for the CIFS service on [BACK_SERVER_1] as [ADMIN_USER]. We can inject it and access the resource.

Attack WITHOUT Protocol Transition

If the TRUSTED_TO_AUTH_FOR_DELEGATION flag is not enabled, the attack is harder.

We cannot impersonate an arbitrary user. The S4U2self step will still work, but the ticket it returns will not have the "forwardable" flag. If we try to use it for S4U2proxy, it will fail with the error KDC_ERR_BADOPTION.

In this scenario, the attacker must first obtain a legitimate service ticket that a user has requested for the front-end service (our compromised server, [FRONT_SERVER_1]$). We are limited to impersonating only the users who authenticate to this server.

Let's suppose we have captured a ticket from user [EXAMPLE_USER] for HTTP/[FRONT_SERVER_1].

Now, we modify our Rubeus command. Instead of /impersonateuser, we use the /tgs parameter to provide the captured service ticket of [EXAMPLE_USER].

  • /tgs: The captured service ticket from the user ([EXAMPLE_USER]) to the front-end service.

Rubeus will use this ticket to directly perform the S4U2proxy request.

We obtain a ticket for cifs/[BACK_SERVER_1] as [EXAMPLE_USER]. Even if they aren't a Domain Administrator, [EXAMPLE_USER] might have access to interesting files on that server. The rest of the attack (createnetonly, steal_token) is identical, but we are now operating as the user [EXAMPLE_USER].

Última actualización