Kerberos delegation has been around for a long time (Windows Server 2000 to be exact), but more often than not, when speaking to engineers who manage or work with Active Directory, they’re not familiar with all the various implementations of Kerberos delegation, their uses, and some ways they can be abused. What I find funny, is that most people confuse Kerberos delegation with delegated permissions.
The practical usage of Kerberos delegation is to enable an
application to access resources hosted on a different server. One example is
when a web server needs to access resources for the website hosted somewhere else,
such as a SQL database. Instead of giving the service account running the web
server access to the database directly, you can allow the web server service
account to be delegated to the SQL server service. Once a user logs into the
website, the web server service account will request access to the SQL server
service on behalf of that user. This allows the user to get access to the
content in the database that they’ve been provisioned to, without having to
provision any access to the web server service account itself.
Types of Kerberos Delegation
There are a few flavors of Kerberos delegation since it has evolved over the years. The original implementation is unconstrained delegation, this was what existed in Windows Server 2000. Since then, more strict versions of delegation have come along. Constrained delegation, which was available in Windows Server 2003, and Resource-Based Constrained delegation which was made available in 2012, both have improved the security and implementation of Kerberos delegation. I’ll dive deeper into each type of delegation, and it’s usage below.
You can configure delegation on a computer or user account within Active Directory, but user accounts must have a servicePrincipalName (SPN) set. Below is a screenshot showing the Delegation tab in Active Directory Users and Computers, and an explanation of some of the options on that page.
In yellow, the first option allows you to configure an
account so that it is NOT allowed to be trusted for delegation. This is most
commonly used on sensitive or administrative accounts that should never be used
for delegation. The second option, in green, allows you to configure an account
for unconstrained delegation. The third option, in red, allows you to configure
an account for constrained delegation.
This is the original implementation of delegation, and also
the least secure. What does unconstrained delegation actually do? Under the
covers, when unconstrained delegation is configured, the userAccountControl
attribute of the object gets updated to include the “TRUSTED_FOR_DELEGATION”
flag. When an object authenticates to a host with unconstrained delegation
configured, the ticket-granting ticket (TGT) for that account gets stored in
memory. This is so the host with unconstrained delegation configured can
impersonate as that user later on if needed.
So imagine a scenario where a privileged account
authenticates to a host with unconstrained delegation configured, you now can
access any configured service within the domain as that privileged user. Jeff
Warren does a great write-up of a similar attack here.
To take it a step further, what if there
were ways to force privileged accounts to authenticate to your host
automatically? Using the ‘printer
bug’ you can get a domain controller to authenticate to your host, leaving
the TGT for that account in memory. Since mechanisms like the ‘printer bug’
exist, unconstrained delegation is very insecure and should not be leveraged,
if at all possible. One thing to note is that Domain Controllers, by default,
are configured with unconstrained delegation. This is required, and since your
Domain Controllers should be much more secure than a random application server
hosting a service, it should not be a problem.
Introduced in Windows Server 2003, constrained delegation takes it a step further by allowing you to configure which services an account can be delegated to. This, in theory, would limit the potential exposure if a compromise occurred.
One restriction to note for constrained delegation, is that
it does not work cross forest. When constrained delegation is set on an
account, two things happen under the covers:
The userAccountControl attribute for the object
gets updated with the “TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION” flag
The msDS-AllowedToDelegateTo attribute gets
populated with the SPN configured on the delegation tab
Abusing constrained delegation is different than abusing unconstrained delegation. One common way it can be abused is if you’re able to compromise the plaintext password or NTLM hash of a user account configured for constrained delegation. Using a tool like Kekeo, you’re able to request a TGT for the account you have the password for, execute the TGS request for any user (as long as they’re not marked ‘Sensitive’), and then inject the ticket and access the service you requested as that user. This type of abuse will be covered in a future blog.
Resource-Based Constrained Delegation
Introduced in Windows Server 2012, Resource-Based
Constrained Delegation changes how you can configure constrained delegation, and
it will work across a trust. Instead of specifying which object can delegate to
which service, the resource hosting the service specifies which objects can
delegate to it. From an administrative standpoint, this allows the resource
owner to control who can access it. For example, instead of specifying with
constrained delegation that the WebServer service account can delegate to the
SQL Service to access the database, you can specify on the SQL server service
account that the WebServer service account has permissions to delegate access
Resource-based Constrained Delegation is configured by
populating the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on the target
resource, with the SID of the object that is allowed to delegate to it. To
configure Resource-based Constrained Delegation, you actually need to leverage
PowerShell, there is no GUI component within Active Directory Users and
Computers and the Attribute Editor page does not allow for manual modification
of this attribute. You can read more about Resource-Based Constrained
Delegation and ways to abuse it in my other blog here.
Identifying Existing Kerberos Delegation
Now that you understand some of the basics for the different types of delegation and some ways they can be abused, I want to share with you a method you can use to wrap your head around what types of delegation may already be configured within your environment. Specifically looking to highlight insecure scenarios, such as unconstrained delegation being configured on objects other than Domain Controllers. Microsoft actually offers a script to assist with this via their technet gallery. The script will identify accounts with unconstrained, constrained, and resource-based constrained delegation configured. It will also highlight information and potential warnings about the configurations it identifies.
Hopefully, I’ve been able to clear up any confusion around what Kerberos delegation is and how it works. In the future, I’ll be writing a blog on how to abuse constrained delegation. For now, check out some of our other STEALTHbits blogs on Kerberos delegation:
You write in types of kerberos: Resource-Based Constrained delegation which was made available in 2016 and when starting with the chapter it says : Introduced in Windows Server 2012, Resource-Based Constrained Delegation changes how you can configure constrained delegation.
So, is it available in server 2012, in server 2016 or since the year 2016? It is not really clear to me 😉