
This article covers the key aspects of the Kerberos protocol and its constrained delegation mechanism. You’ll learn how the S4U2Proxy and S4U2Self extensions work, and what risks arise from delegation of access. We explain why attackers can exploit delegation to gain privileged access to resources, and provide recommendations on how to protect your network from such attacks.
Disclaimer: We are aware that some photos or articles may contain Russian language captions. But isn’t it great to use their own language against them?
In the previous part, we already discussed how attacks on Active Directory work through Kerberos unconstrained delegation. We also briefly explained the basics of this protocol to make it easier for readers to understand the following material. Now it’s time to take a closer look at the risks that constrained delegation hides and how it can be attacked.
Constrained delegation was introduced in Windows Server 2003 to reduce the scope of delegation and make the system more secure. A service with constrained delegation can act on behalf of any user, but only when accessing specific, predefined services.
Let’s consider a general constrained delegation scheme using only the Kerberos protocol:
User normally receives a TGS ticket with the Forwardable flag to access Service A and sends it to the specified service.
Service A forwards the received TGS ticket to the domain controller to access Service B on behalf of User. As mentioned earlier, the TGS ticket contains the username for which it was intended. Thus, Service A proves that User actually accessed it.
The domain controller checks that the msds-allowedtodelegateto attribute of “Owner A” contains the SPN of Service B and, if the check is successful, sends Service A a Forwardable TGS ticket to Service B for User.
It is important that as a result of successful execution of the S4U2Proxy request, a Forwardable TGS ticket is always returned.
The S4U2Self (Service for User to Self) extension is used when a client authenticates to a service with constrained delegation using any protocol other than Kerberos, such as NTLM. In such cases, the client can authenticate but is unable to pass a TGS ticket because the Kerberos protocol is not involved. S4U2Self allows a service to obtain a Forwardable TGS ticket to itself from a domain controller on behalf of the requesting user.
For an account to use constrained delegation with cross-protocol transition (S4U2Self), a special flag called TRUSTED_TO_AUTH_FOR_DELEGATION must be set in the UserAccountControl attribute of that account. The flag corresponds to the integer value 16777216.
As an example, let’s consider the limited delegation mechanism with a protocol change:
User authenticates to Service A using any non-Kerberos protocol, including NTLM.
Service A requests a Forwardable TGS ticket from the domain controller on behalf of User.
The domain controller verifies that the account “Owner A” has the TRUSTED_TO_AUTH_FOR_AUTHENTICATION flag set in the UserAccountControl attribute.
If the check fails, for example, when the TRUSTED_TO_AUTH_FOR_DELEGATION flag is not set or the user belongs to the “Protected Users” group, the service will receive a TGS ticket without the right to transfer (Nonforwardable) for this user to Service A.
Thus, the ticket issued in response to the S4U2Self request may or may not contain the Forwardable flag – this depends on the settings of the account and the service. If the settings allow delegation, the ticket will have the Forwardable flag; if not – without it, which limits the possibility of further transfer of the ticket to other services.
In the future, the S4U2Proxy extension is used to obtain a Forwardable TGS ticket to Service B on behalf of User.
Importantly, an S4U2Self TGS ticket request on behalf of an arbitrary user can be initiated by any account that owns the SPN, without waiting for the specified user to authenticate.
Attack condition: password (NT hash) to an account that has the right to limited delegation with protocol change to a specific service.
Some options for fulfilling the condition:
The password to a user account can be obtained as a result of a Kerberosting attack or picked up offline as a result of intercepting a Net-NTLMv2 hash.
Passwords (NT hashes) can be extracted from the server’s or workstation’s RAM.
The result of a successful attack: access with administrative rights to the server intended for the functioning of the service to which delegation is performed.
The idea of the attack is to impersonate a privileged user when accessing a service for which limited delegation is configured.
Let’s consider the attack using a practical example from the Exploiting Active Directory lab (available with a paid subscription). The attacker has an svcIIS account with the following delegation settings:
findDelegation.py $Domain_FQDN/$Username:$Password
The svcIIS delegation settings allow remote privileged access to THMSERVER1 using the WinRM service.
As a result, summarizing the above, the following attack sequence is obtained:
Request TGT for user svcIIS
Using the received TGT, request TGS tickets to services HTTP/THMSERVER1.za.tryhackme.loc and WSMAN/THMSERVER1.za.tryhackme.loc on behalf of privileged user T1_Trevor.jones
Using the received TGS tickets, connect to THMSERVER1.za.tryhackme.loc on behalf of privileged user T1_Trevor.jones using PassTheTicket and WinRM
For better understanding, we will carry out the attack in two ways. The first way is a bit excessive, but it illustrates each step separately well. The second way is more automated and closer to practice.
Request a TGT for the svcIIS account:
tgt::ask /user:$Username /domain:$Domain_FQDN /password:$Password
Request a TGS ticket to HTTP/THMSERVER1.za.tryhackme.loc on behalf of T1_Trevor.jones:
tgs::s4u /tgt:$path_to_TGT /user:$Username /service:$SPN
Similarly, we request a TGS ticket from WSMAN/THMSERVER1.za.tryhackme.loc
Using Mimikatz, we load the obtained TGS tickets into the LSA for PtT:
For clarity, let’s make sure that the tickets are actually loaded:
List of cached Kerberos tickets
Let’s create a new session:
Let’s log in to the created session:
The attack method discussed above is not very practical, as its successful execution requires that constrained delegation be configured specifically for those services that are used for remote connections. This significantly limits the possibility of implementing such a scenario in real-world conditions.
As you can see from the illustration, if at least one of the services of the account has constrained delegation configured, the attacker can take advantage of this and gain access to other services associated with this account.
However, it is important to remember that if the SPN specifies a port, for example, mssqlsvc\server01.domain.local:1433, it will not be possible to obtain a TGS ticket for the substitute service. In this case, when trying to change the target SPN, the domain controller will return the message KDC_ERR_S_PRINCIPAL_UNKNOWN, indicating that there is no registered SPN.
Let’s try to repeat the attack, but this time we will use scripts from the Impacket set. The first step will be to request a TGS ticket to the HTTP/THMSERVER1.za.tryhackme.loc service on behalf of the privileged user T1_Trevor.jones. This will allow you to check whether limited delegation is configured for the target service and whether it is possible to use the received ticket for further actions.
Thanks to Impacket scripts, the process of requesting a TGS ticket can be automated, which greatly facilitates the execution of the attack and speeds up its implementation.
getST.py -spn $SPN -impersonate $ImpersonatedUsername $Domain_FQDN/$Username:$Password
Export the received TGS ticket to the cache and establish a remote connection, for example using wmiexec:
export KRB5CCNAME=$PathToCacheFile
wmiexec.py -k -no-pass $Domain_FQDN/$ImpersonatedUsername@$TargetDnsName
Access gained, attack completed successfully.
For general knowledge, let’s run the same command in debug mode:
Perform a domain scan to identify accounts with constrained delegation configured but not in use.
Use constrained delegation only for specific services and only when absolutely necessary.
Add critical accounts to the Protected Users group or enable the “Account is sensitive and cannot be delegated” setting in the settings for those accounts.
Create separate accounts for services whenever possible and assign them as service owners.
Ensure that strong passwords are used for service accounts and that they are changed regularly.
Always specify a port when creating an SPN to prevent unwanted delegation.