Our Blog

Constrained Delegation Considerations for Lateral Movement

Reading time ~18 min

The abuse of constrained delegation configuration, whereby a compromised domain user or computer account configured with constrained delegation can be leveraged to impersonate domain users to preconfigured trusted services, is a common attack path in Active Directory. For each trusted service, a unique service ticket is used, that explicitly corresponds to the service type for which it was requested. For example, to access Windows file shares, a CIFS ticket is required. Meanwhile, to leverage the WinRM protocol, a HTTP service ticket is required instead. Compromise of such service tickets aids in lateral movement and further compromise.

There can be, however, cases where the service type of the service that accepts delegated credentials does not, by default, aid in lateral movement. For example, if the account configured with constrained delegation is only allowed to present delegated credentials to the eventlog service, the default service ticket is basically useless. However, using existing tooling, it is possible to change the type of the service ticket, resulting in a ticket that can be used for any other service type. As such, constrained delegation can still be abused for lateral movement, even if the service type of the preconfigured trusted services is of no use.

This blog post aims to examine such lateral movement scenarios, using service tickets on both Linux and Windows hosts, when impersonating domain user accounts, including Domain Admins. Although the abuse of Kerberos delegation is a deeply researched topic, for posterity’s sake, the next section aims to summarise what delegation is, and why it should be of interest to an adversary.

a bit of recycled delegation theory

Delegation in an Active Directory environment simply refers to the delegation of credentials, by which service accounts can impersonate user accounts and access various services on behalf of them. The concept of credential delegation and impersonation is necessary to avoid the double hop problem.

Consider the following scenario where a happy user authenticates to a web server (first hop) that interacts with a back-end database (second hop). Upon successful authentication to the web application, the web server will create a separate process for that particular user with their authentication token. However, the user credentials will not be stored anywhere in the web server, therefore, it will not be possible for the service account of the web server to use these credentials to authenticate to the database. As a result, the connection attempt to the database server will return an “Access Denied” error message, and the user is now sad and disappointed.

Figure 1 – A happy user authenticates to a web application hoping to successfully connect to the database.

To overcome this limitation, Microsoft introduced the concept of credential delegation, which enables an application (e.g. web server) to access resources hosted by a different application on a different server (e.g. database server) on behalf of a user. To avoid the double hop issue in the example above, the web server needs to be trusted for delegation, or the database service needs to be explicitly configured to accept delegated credentials from the web server.

There are three flavours of delegation; unconstrained, constrained, and resource-based constrained delegation. Depending on the flavour of delegation, and should certain criteria be met, delegation can be abused to compromise privileged accounts or Domain Controllers directly.

Unconstrained delegation is the oldest delegation flavour and the least secure. When a host is configured with unconstrained delegation, the Ticket-Granting Ticket (TGT) for the account authenticating to that host is stored in its memory. The TGT can then be used by the host to impersonate that account and gain access to various services by requesting the respective Ticket-Granting Service (TGS) tickets. Therefore, compromise of a host configured with unconstrained delegation would result in the compromise of the TGTs stored in its memory, thereby allowing for the impersonation of the respective accounts to available services. Evidently, should the compromised TGTs be associated to privileged accounts, the compromise of the domain may be achieved.

To avoid the double hop limitation of the aforementioned example, the web server could be configured with unconstrained delegation in order to access the back-end database service, or any other service for that matter, on behalf of the authenticating user. As such, compromise of the web server would allow for the compromise of the user’s TGT, allowing for further impersonation to other services.

Constrained delegation was introduced to address the security concerns associated with unconstrained delegation. It allows for the configuration of specific services which credentials can be delegated to, as opposed to delegation to any service allowed with unconstrained delegation. In the aforementioned example, the web server could be configured to only present delegated credentials to the database server, instead of any other arbitrary service.

Resource-based constrained delegation further refined constrained delegation, by allowing the target service to select which objects can delegate to it instead, thereby allowing the service itself to control who has access to it. In our example, the database server could be configured to only accept delegated credentials from the web server in particular.

As mentioned earlier, delegation is a deeply researched topic, and although these flavours of delegation are more secure than their predecessors, they can be abused should certain criteria be met. The following research elaborates further on Kerberos delegation, and you are highly encouraged to have a look:

Moreover, Daniel López (@DaniLJ94) has released quality content regarding the double hop issue and the flavours of Kerberos delegation. The PDF and video are listed below:

enumerating constrained delegation

In order to allow a computer to delegate credentials using constrained delegation, i.e. to configure the computer to delegate credentials to specific services as opposed to any service mandated by unconstrained delegation, the "Trust this computer for delegation to specified services only" option within the Delegation section in the computer’s object properties needs to be set. For the purposes of this post, we will allow for any authentication protocol, rather than using Kerberos only.

As shown below, the ASGARD-SERVER01 has been configured to present delegated credentials to the eventlog service of ASGARD-SERVER02.

Figure 2 – ASGARD-SERVER01 is trusted to delegate to the eventlog service provided by ASGARD-SERVER02.

As soon as a domain account or a domain-joined computer has been compromised, the environment can be enumerated for accounts configured in such a manner. We should be looking for the msds-allowedtodelegateto attribute, which is populated with the Service Principal Name (SPN) of the target service the corresponding account is allowed to present delegated credentials to. This enumeration can be achieved in many different ways.

One could use PowerView, for example, as follows:

Get-DomainComputer -TrustedToAuth -Properties DnsHostName, MSDS-AllowedToDelegateTo

Figure 3 – PowerView command to list computers allowed to delegate to other computers.

BloodHound can also be used to achieve this. There are multiple queries one could use to enumerate delegation configuration. A good cheatsheet for BloodHound queries can be found on Hausec‘s page.

interesting services for lateral movement

Kerberos interactions will commence with a domain object sending its credentials to receive a TGT, should these credentials be valid. Thereafter, the provided TGT can be used to request access to resources in the domain such as services running on servers. The access will be granted with a TGS linked to the corresponding service, as explained earlier.

Therefore, knowledge of the ticket issuance process and identifiers for the various Windows services can be beneficial to adversaries, and aid in lateral movement. The ADSecurity blog post on silver tickets provides the mappings of the service ticket type required to access specific services, which can be a useful resource when using these for lateral movement. These mappings are shown below.

Figure 5 – Service type and service ticket mapping for further lateral movement attacks.

the linux component

Since ASGARD-SERVER01 is configured to present delegated credentials to ASGARD-SERVER02, the ASGARD-SERVER01 machine account NTLM hash is required to abuse the delegation configuration. Assuming that we have somehow, magically, compromised this host with SYSTEM privileges, we can easily retrieve its hash using Impacket’s secretsdump. Impacket is not the only way to achieve this, but it does the trick.

Figure 6 – Impacket’s secretsdump used to obtain the computer account NTLM.

It is worth noting that computer account passwords change periodically. Refer to this for further information. For this reason, the NTLM hashes used to conduct the attacks described below may not be the same, since I took the screenshots on different days and lab configuration.

We can now use the compromised computer account to abuse the delegation relationship. From a Linux host, I used Cerbero from Zer1t0. Cerbero is a tool developed to interact with Kerberos, and it’s written in Rust.

In our scenario, although we can delegate to the eventlog service, we are interested in delegating to services such as CIFS, HTTP, HOST and RPCSS to move laterally using PsExec, WinRM or WMI. We will therefore need to rename the service, by replacing the legitimate service our TGS was created for, with the service we want to target. The service replacement is performed locally and it is not validated by the remote server we will be delegating to. Therefore, we can simply replace the eventlog service with CIFS using Cerbero as follows:

cerbero ask -vv --impersonate asgard.local/arthur.da -k 10.50.30.10 --user 'asgard.local/ASGARD-SERVER01$' --rc4 5ffecaaedb763ea283d47ac8becf88f9 --service eventlog/ASGARD-SERVER02.asgard.local --rename-service CIFS/ASGARD-SERVER02.asgard.local

Figure 7 – Using Cerbero to perform the S4U process to obtain a TGS for the CIFS service on ASGARD-SERVER02.

With the new ticket stored within the ASGARD-SERVER01$.ccache file, we can use the KRB5CCNAME environment variable with Impacket’s PSExec to remotely connect to ASGARD-SERVER02 as follows:

export KRB5CCNAME='/tools/impacket/ASGARD-SERVER01$.ccache'
psexec.py -k -no-pass asgard.local/arthur.da@ASGARD-SERVER02.asgard.local

Figure 8 – Setting the KRB5CCNAME kerberos environment variable to include the TGS requested with Cerbero.
Figure 9 – Using Impacket’s PSexec to remotely access a system.

There are some OPSec considerations here. The service installed by Impacket can be flagged by AVs. We could alternatively approach the situation as follows:

  1. With a CIFS ticket we can access SMB shares and copy files to the remote host. Since we can write to the ADMIN$ share, we can install a service remotely using a binary of our choice, not necessarily a PsExec service binary. For instance, we could create an EXE that adds a local administrator and configure a new service to execute that binary.
  2. Use SysInternals’ PsExec tools, but we will need to perform the attack from a Windows box in this case. If you are at the stage of abusing delegation, you should have SYSTEM privileges on other Windows hosts within the domain (e.g. ASGARD-SERVER01). You can therefore use Rubeus to replicate the S4U attack and impersonate a user on the targeted system.

the windows component

From a Windows perspective, the following requirements have already been met:

  • Interactive session on the domain-joined Windows host ASGARD-SERVER01.
  • SYSTEM privileges on ASGARD-SERVER01.

To avoid issues while requesting Kerberos tickets, I tend to create a “fake” network CMD session using Runas supplied with the /netonly flag, where I can provide fake user credentials.

Figure 10 – Starting a fake CMD process using Runas with the /netonly flag.

We can now use the spawned CMD process to request tickets using Rubeus. The command we’ll use is quite similar to the one used before with Cerbero:

Rubeus.exe s4u /user:ASGARD-SERVER01$ /rc4:5ffecaaedb763ea283d47ac8becf88f9 /impersonateuser:arthur.da /msdsspn:eventlog/ASGARD-SERVER02.asgard.local /altservice:cifs /ptt

The previous command will start a three step process known as S4U (Service for User). The first Kerberos interaction will create a TGT for the computer account ASGARD-SERVER01$. The second Kerberos interaction will perform the S4U2Self process and produce a TGS impersonating the targeted user. The last interaction will perform the S4U2Proxy process, which will produce the TGS to access the CIFS service on ASGARD-SERVER02 as the impersonated user. Note that the service renaming will be applied before requesting the TGS.

Figure 11 – Requesting a TGT for the computer account ASGARD-SERVER01.
Figure 12 – S4U2Self to get a TGS for arthur.da on ASGARD-SERVER01.
Figure 13 – S4U2Proxy request for the eventlog service on ASGARD-SERVER02 to impersonate arthur.da that will be replace with a CIFS ticket.

psexec

Rubeus’ /ptt flag will cache the ticket in our current session and we should be able to list the remote C$ share as arthur.da on ASGARD-SERVER02:

Figure 14 – The imported TGS impersonating arthur.da granted rights to list \\ASGARD-SERVER02\C$.

Since the attack was successful, we can now run SysInternals’ PsExec:

Figure 15 – PsExec using the obtained TGS impersonating arthur.da.

Sysinternals’ PsExec is a better alternative to move laterally within a domain network because the binary files are all signed by Microsoft and thus, trusted by some anti-virus software. However, PsExec is not the best choice for lateral movement and it can easily be detected and blocked. For this reason, let’s explore how we can take advantage of a constrained delegation attack path to move laterally using WinRM and WMI.

winrm

Instead of requesting a CIFS ticket, we can set the /altservice value to HTTP in order to move laterally using WinRM. The process is exactly the same. However, it is important to note that a valid logon session is required for this scenario, so we will not be able to start WinRM from within our “fake” CMD process.

The following command will import an impersonated TGS for the HTTP service on ASGARD-SERVER02 and arthur.da domain admin (note the /altservice flag):

Rubeus.exe s4u /user:ASGARD-SERVER01$ /rc4:5ffecaaedb763ea283d47ac8becf88f9 /impersonateuser:arthur.da /msdsspn:eventlog/ASGARD-SERVER02.asgard.local /altservice:http /ptt

The S4U process is as described above. Once executed successfully, the ticket should be available, as seen below by the output of the klist command:

Figure 16 – Rubeus klist showed the HTTP ticket was imported successfully.

If we connect to ASGARD-SERVER02 using Enter-PSSession we’ll be able to execute commands remotely. If we execute klist on the target host, we’ll notice that the HTTP service ticket is available there as well:

Figure 17 – Enter-PSSession allowed to execute remote computers with just an HTTP TGS.

wmi

Similarly, we can also use wmic. Note that although wmic does not return any output, we can execute commands remotely such as executing a binary. For the purposes of this blogpost, the PoC is merely the creation of a TXT file on disk, to show that the command has been executed successfully.

For WMI, we need two different service tickets: HOST and RPCSS. Once more, we can use Rubeus to request these two service tickets following the S4U process.

  • S4U HOST service ticket command

Rubeus.exe s4u /user:ASGARD-SERVER01$ /rc4:5ffecaaedb763ea283d47ac8becf88f9 /impersonateuser:arthur.da /msdsspn:eventlog/ASGARD-SERVER02.asgard.local /altservice:host /ptt

  • S4U RPCSS service ticket command

Rubeus.exe s4u /user:ASGARD-SERVER01$ /rc4:5ffecaaedb763ea283d47ac8becf88f9 /impersonateuser:arthur.da /msdsspn:eventlog/ASGARD-SERVER02.asgard.local /altservice:rpcss /ptt

Running klist will show us the two tickets are now available:

Figure 18 – HOST and RPCSS service ticket successfully imported to impersonate arthur.da using WMI for lateral movements.

We can then use Invoke-WmiMethod within PowerShell to execute a command on the remote host via WMI:

Figure 19 – Invoke-WmiMethod that will run a command as arthur.da on ASGARD-SERVER02 via WMI. The output will be stored in the C$ drive.
Figure 20 – The file was successfully created and was available on the remote host, confirming the WMI command was executed as expected.

The command execution can now be leveraged to obtain a remote shell or even stage a Cobalt Strike beacon.

sensepost @ ringzero

Similar content will be delivered at Ringzer0 #BackToVegas on our Advanced Active Directory Exploitation (AADE) course. The course extensively covers Active Directory attacks with hands-on practical scenarios, as used during real penetration testing engagements. Students will be provided with access to an isolated lab environment, configured to simulate a multi-forest domain network. Should you decide to join us, you will have the opportunity to conduct an engagement against an Active Directory environment from the beginning to the end, through multiple practicals, including delegation abuse, abuse of Group Policy Objects, and attacks against forest trusts. For more details about the course, structure, and content please refer to the official Ringzero course page.

Thanks for reading, and please reach out to us should you have any questions or recommendations!