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.
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:
- Slides: You Do (Not) Understand Kerberos Delegation.pdf
- YouTube: You Do (Not) Understand Kerberos Delegation Video
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
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
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.
the linux component
ASGARD-SERVER01 is configured to present delegated credentials to
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.
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
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
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:
psexec.py -k -no-pass asgard.local/arthur.da@ASGARD-SERVER02.asgard.local
There are some OPSec considerations here. The service installed by Impacket can be flagged by AVs. We could alternatively approach the situation as follows:
- 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.
- 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
SYSTEMprivileges 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
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.
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.
/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
Since the attack was successful, we can now run SysInternals’ PsExec:
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.
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
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:
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:
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:
We can then use
Invoke-WmiMethod within PowerShell to execute a command on the remote host via WMI:
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!