Trust your delegations. Don't just delegate your trusts. My name is Darryl Baker. I am a security consultant with Trimarc Security. I am the creator of Active Directory Hacking Village, also known as Identity Security Village. And I'm a purple teamer.
Today, we're going to talk about Kerberos authentication and delegation, different types of Kerberos delegation, trending Kerberos delegation attacks, including KrbRelayUp; some delegation behavior across AD trusts, as well as delegation behavior across your Cloud Infrastructure, such as Azure AD or Azure VMs when using Hybrid Active Directory join; specific attack vectors for delegation in Hybrid AD, as well as mitigations for all of this.
So to start off, what is Kerberos? Kerberos is a network authentication protocol. It is based on a ticket paradigm, and it allows for two trusted hosts to authenticate securely over an insecure network using a trusted third party. So this allows for communication across intranets, internets, and other types of networks, even if you don't have any other infrastructure in place aside from a domain controller and then these two trusted hosts.
It is the preferred authentication method for Windows domains, although it is not the only authentication method. NTLM is also commonly used in Windows domains, though there's a lot of attacks that are targeted around NTLM. But NTLM is always used with Windows machines if either a server or the client is not domain joined. So NTLM, very active still in the environment, but Kerberos is definitely more secure and preferred.
To start off, before we can dig too deep into delegation and what Kerberos delegation looks like, we first have to talk about Kerberos authentication. So Kerberos authentication consists of about six different steps. And we'll go through those briefly.
So step one is known as the authentication service request, and there's actually a piece of authentication that happens here. The client will take a timestamp, and then encrypt that timestamp using the hash of its password, and send that over to the domain controller. The domain controller knows the client's password, so it uses the hash of the client's password. In order to decrypt that, it checks the timestamp, and it makes sure that time is within five minutes.
If all of that checks out, then the domain controller replies with a authentication service reply. And in this reply, there is a ticket granting ticket known as a TGT. This TGT is good for 10 hours by default, and it's used for all subsequent service ticket requests after that. The main purpose of a TGT is to prove that that client is that client whenever requesting service tickets to any other target resource.
So with step three, the client will then use the TGT and present that to the domain controller and say, I would like a service ticket for some target resource. The domain controller will check out the TGT, make sure the client is who they are, and then replies back with the service ticket, also known as a TGS. Once the client has the service ticket for the resource server, it will present that service ticket to the target resource. This is known as an application request. And the target resource will look at the service ticket, make sure the information inside of the service ticket is good to go. Everything checks out and that this client does indeed have permissions to access the service or this resource.
Off to the right-hand side, you can see that we have a 5.1 and a 5.2 step. Basically, what this is-- this is known as a PAC verify request and then a PAC verify response. The reason why it's in yellow, and we've got the dot 1 and the dot 2 is because this step does not always happen.
Let's dig in a little bit deeper into that. So what the PAC actually is is a privileged attribute certificate, and it is used to hold some security information about that client. So when that first ticket granting ticket is sent to the client from the domain controller, a PAC is sent with it.
And some of the data that's inside of this PAC structure include the username, SAM account name, and, importantly, group membership. So when a target resource receives the service ticket, decrypts it, and looks at the PAC, if a user is part of, let's say, the domain admins group, once they receive a token for the service-- so let's say, a log on token-- they will receive the token as a domain administrator for that service or for that resource.
Now, in 2014, the algorithm used to encrypt the PAC was accidentally disclosed by Microsoft. And so Microsoft completely revamped what the PAC data structure looks like and pushed out updates. This was back in 2014, so all subsequent versions of Windows Server also include this new updated PAC structure.
So what happens is there's a new registry key that you can see right here on the screen. By default, this registry key is set to 1. And what this means is, if a target resource receives a PAC that does not meet the new PAC structure, this is when we go back to that 5.1 step. The target resource will send the bad PAC to the domain controller and say, I need for you to verify that this PAC is legitimate. If everything checks out, Kerberos authentication continues as usual.
Now, you can change this registry key value if you'd like. By setting it to 0, it basically reverts the update. And no matter what the PAC structure in place is, authentication will always continue on. Now, that is not to say that the client will always get authenticated, but the authenticating-- the authentication process will continue.
If you set it to 2, this enforces the new PAC structure. It's the most strict, but it's not necessarily the recommended. But with enforcement, if the PAC meets the new data structure, authentication continues. If the PAC does not meet the new data structure, then that client that's trying to authenticate to the service is just explicitly denied and will not have access to that service until a PAC with a proper structure is presented.
So now we can move on to Kerberos delegation. For this presentation, we're specifically talking about Kerberos delegation inside of Active Directory. Within Active Directory, delegation means impersonation. Delegation is when an object has the ability to act on behalf of another object when authenticating to some resource or service.
So that being said, depending on the type of delegation that you have in place, you can impersonate a domain controller, a domain admin, or any other object that's inside of your environment. So as you can imagine, this opens up attack vectors everywhere. There are two main types of Kerberos delegation. There is unconstrained delegation, and there's constrained delegation.
Most of this presentation is going to be focused on constrained delegation, but I do want to give you some background about unconstrained delegation because it's still pretty common. I do security assessments for Active Directory for a living, and I run into unconstrained delegation quite a bit. Also, third party vendors a lot of times will say, in order for their product to work, unconstrained delegation is the only way to make it work. Sometimes that's true, and sometimes it's not, but so let's talk about that.
With unconstrained delegation, any object that has unconstrained delegation has the ability to impersonate any other object in your domain when accessing any other target resource. When this happens, for the impersonation, they actually go to the domain controller and say, I would like a service ticket on behalf of some other user. And the domain controller will give them a TGT for that user.
So that ticket granting ticket for the other user is actually forwarded to the object that has delegation in place. And then using that TGT, the delegated object can then go out and request service tickets as normal. This is quite a bit risky in that, if this machine gets compromised-- it has unconstrained delegation configured-- we can use a tool, such as Mimikatz, to dump all the ticket granting tickets from the computer's memory.
Hopefully, we'll find one that's got some kind of elevated domain permissions, or even maybe local permissions that are higher than the ones that we have so far. We can use attacks such as pass the ticket of the elevated user, and we can request all kinds of service tickets on these users' behalf that we've just dumped these ticket granting ticket from memory.
So for an attacker who's in your environment, if they're on a domain joined machine, or a Windows domain join machine, it's very easy in PowerShell to enumerate what accounts have this configured. You're just going to look for the trusted for delegation attribute that is set to true.
So when possible, you want to not use unconstrained delegation. In 2003, Kerberos constrained delegation was implemented. And in 2012, with server 2012 and 2012 R2, there's actually two extensions that were added to constrained delegation. These are called S4U extensions. There's an S4U to proxy and an S4U to self, and we'll talk about those here in a little bit.
But what's important about constrained delegation is two pieces. With constrained delegation, a delegated object still has the ability to impersonate any other user in your environment. However, they're constrained to a specific service or a specific resource. You can also constrain them to a specific protocol to be used.
So you can say that client A can only access print server B using Kerberos. So there's a lot more control over what could happen. Even if that service ticket was somehow compromised, you would still only have access to that one target service and only using that protocol. With constrained delegation, there's three different subtypes.
We've got a typical Kerberos constrained delegation. We've got Kerberos constrained delegation with protocol transition, and we've got resource-based constrained delegation. With constrained delegation, you can tell that a machine or any other object, in theory, has constrained delegation in place because of the Msds-allowedtodelegate attribute being in place. The value of that attribute will be whatever it is that it has the ability to delegate to.
So Kerberos authentication looks pretty similar. Here we're going to have a client named Einstein who is accessing some web application hosted on a web server. That web application has the ability to go out to a file share and download files for this client. So walking through these steps, Kerberos authentication starts as normal. The client goes to the DC to get his TGT. He uses that TGT to then get a service ticket for the web server.
The web server realizes that the client also needs to access this file share, and this web server is configured for constrained delegation to the file share. So the web server will then use this new S4U2Proxy extension to create a special service ticket to go out to the DC requesting a service ticket on behalf of the client to the file share. This is where step five comes into play.
The web server actually goes to the file share on behalf of the client. Authentication happens as normal, and then this is returned to the client in step six. Again, one thing that's important to note is, here in step 4, by using that S4U2Proxy service ticket, the web server never needed the TGT of that client. So even if that web server was compromised, none of the TGTs exist in memory for that client.
Constrained delegation with protocol transition is pretty similar to typical constrained delegation. The biggest difference is here our client is out of band from the rest of the domain. So maybe he's coming from the broad internet and doesn't have direct access to the intranet. He's still going to access this internet-facing web server, and he's still going to retrieve a file from the file share.
Things work a little bit differently here, though. Because in the first step the client doesn't have direct access to the domain controller, he needs to authenticate directly to the web server. And he can authenticate via any authentication protocol that's configured on this web server.
So he can use NTLM, for instance. He could use Kerberos if he wanted to. It could be basic auth, anything here.
So once the client is authenticated to the web server, the web server does something kind of tricky. So it uses this S4U2Self service ticket, and what that is is it is requesting access from the domain controller to this web server on behalf of the client. So it is saying that he wants to have a service ticket to itself on behalf of that client.
The DC will give that service ticket to the web server. The web server can then use that service ticket to then create that S4U2Proxy service ticket request, as we saw on the previous step, of requesting access to the file share. Then in step four, your normal application authentication continues, and in step five, that response is then given back to the client.
So a little bit different. We have that extra step that's in there for the S4U2Self. Now, what's really interesting about constrained delegation with protocol transition is that first step. Because the authentication happens out of band, there is no true validation of what protocol was used for the authentication, or even if the authentication happened.
So when step two happens, and the web server goes to the DC with the S4U2Self service ticket, the DC implicitly trusts that the web server has had some kind of authentication with this client. So as long as this web server is configured with this TRUSTED_TO_AUTH_FOR_DELEGATION attribute, it can always request an S4U2Self to itself on behalf of any client, technically regardless if authentication has truly happened. So that does open up another pathway, potentially, for attackers to get in because no real authentication out of band technically has to happen.
So here's the tricky one, resource-based constrained delegation. Resource-based constrained delegation is kind of backwards compared to all of the other delegation types that we talked to before. With resource-based constrained delegation, it moves the responsibility and the administration of delegation from domain admins to the server admins, or to the service admins.
And what I mean by this is typically we've gone into Active Directory. In Active Directory we've said, service A can delegate to service B. So when service A goes to service B, the S4U2Proxy tickets get created. The domain controller verifies that delegation is in place, and it's configured on service A, and delegation continues.
With resource-based constrained delegation, this delegation is actually configured on the target resource itself. So let's say it's a computer object. This would be configured on the computer object itself, and the msDS-allowedToActOnBehalfOfOtherIdentity attribute. So the domain controller is not involved in that at all.
Now, in order to configure this on a service, you only need right access to that computer object. So if you're the owner of a computer object, or you have right privileges to a computer object, you can configure it for this resource-based constrained delegation. No need for domain administration in place.
We're going to talk quite a bit about resource-based constrained delegation once we get into some of the delegation attacks because it is usually a pretty good starting point, simply because of the lower level privileges that are required in order to create this delegation. That's kind of how delegations work in a nutshell. Basically they said, I could be anything that I wanted to be, so why not become a domain controller?
So there are some interesting trends when it comes to constrained delegation attacks. One of them is around SPN modification. So an SPN is required for any service that you want to access. Any target resource, any target service will always have an SPN configured on it.
SPN stands for service principle name, and it consists of either two or three parts. The first part is a service class, such as Cifs, or https, or host. The second part is the hostname. And if the third part is configured, it typically holds the domain name.
Now, one thing to note is that all computers-- all computer objects, when created, automatically have to SPNs assigned to all of them, and they're both for host. The host service class is what allows you to actually log on to a computer when you're logging on to the computer via the network. So all computer objects will have an SPN just by default.
Now, what's interesting is the way that service ticket validation works to a service is that service ticket is encrypted using the hash of the password of the service account associated with that service. So when you present that service ticket to a target service, it verifies that it can decrypt that service ticket using its password's hash. And then it looks inside the PAC, and it verifies who you are and what you have permissions to.
An interesting part of this is the service ticket is actually made up of two parts. There's an encrypted part, and there is an unencrypted part. Now, the SPN name is actually part of the unencrypted part, so you can always see what target service it is that a client is trying to authenticate to.
This being said, this means that an attacker who's compromised the system with Kerberos constrained delegation configured can modify the portion of the SPN to authenticate to another service on that same resource. So for instance, if you have a server that is a file server, as well as a web server, and you've got a service ticket that is configured for Cifs/targetmachin.domain.corp, an attacker can potentially replace Cifs with https to try to authenticate to the web services on this machine.
Then remote code execution could potentially happen with some tools, like WinRM. Another very common service class replacement that happens is to host, and tools like PsExec can be used to try to execute remote code as well.
Back to resource-based constrained delegation attacks. Why is resource-based constrained delegation such a juicy resource as far as attack vectors for attackers? Well, one is that write privileges are the only thing that are required on that computer object in order to configure RBCD.
The second thing is out of the box, by default, there is a configuration in Active Directory known as Machine Account Quota. Machine Account Quota is the number of machines that any user-- regardless of their permissions in the domain, any user can create these domain computer objects. By default, this is set to 10. So if you do not change this to 0, that means that any user in your environment can create 10 domain computer objects.
And actually, there's been some proof of work to show that each one of those domain computer objects that gets created will also inherit the machine account quota. So I think it's 111 different machine accounts can be created in a chain if done properly. So privilege escalation is typically the goal of this attack, and it works in conjunction with a machine that has constrained delegation in place.
So typically, you're going to want a machine that has resource-based constrained delegation, as well as a compromised machine that has constrained delegation. So most of the work goes into finding a machine that has compromised-- that you can compromise that has constrained delegation in place. And then nowadays, the most common way to get a machine with RBCD is to just create it.
So one common way that this attack works is an attacker will create some machine object or make a computer object in your domain, and configure it with resource-based constrained delegation. Using another attacker controlled machine-- so we'll say this is machine 2-- we'll add that machine to that first computer object that we created, RBCD attribute.
So this means that machine 2 can now impersonate any user, including domain admins, when authenticating the services on machine 1. So we can use a tool like Rubeus to form Kerberos tickets in order to request an S4U2Self on behalf of machine 2 impersonating a domain admin onto machine 1. And then we can use that to request an S4U2Proxy to get back to itself as the elevated user.
So now, on this machine 1, which is just a computer object that you just created in step one, you are now an administrator or a domain admin on that machine. And you can continue to move your way throughout the domain. So again, this is how this looks here. You've got machine 2, which is an attacker-controlled machine configured with Kerberos-constrained delegation.
You've got machine 1 that the attacker created. So this is not necessarily a real machine. This is just a computer object. It's configured with resource-based constrained delegation from machine 2. So now machine 2 can impersonate any user on this machine, and we continue on with that constrained delegation process of the S4U2Self as a domain-- as a domain admin on behalf of machine 2. And then we use that to get an S4U2Proxy back from the domain controller. So now, on machine 1, you have access to all resources on this machine as a domain admin.
This has led into a new attack that kind of appeared I would say about eight months ago. It's known as KrbRelayUp. I call it the new kid on the block because it's got all the right stuff. And it's not just one product. It's actually made up of a few different exploit frameworks for Active Directory, including Rubeus, and KrbRely, PowerMad, ADCSPwn.
It's really cool. Out of the box, with just a couple of clicks, you go through that same process that we just talked about getting domain admin, but there's also a Kerberos relay that happens in the middle as system. And then those system credentials are relayed so that you end up getting system access on that machine. So now you have admin access, as well as full system access to that machine.
KrbRelayUp is a really interesting attack pathway. Essentially, it will basically always work, unless you have LDAP signing and channel binding in place in your environment. That being said, about three months ago, it was discovered that, even if LDAP signing is in place, but you're also using Active Directory certificate services, but you do not have the extended protection for authentication in place, ADCS can be used for that relay, and KrbRelayUp will also still work.
So it works really similar to how your typical constrained delegation worked-- your typical constrained-delegation attack worked, as we said earlier. But here, in step two, you can see that there is a Kerberos relay to LDAP. We'll grab that elevated ticket, as well as using the role based-- the resource-based constrained delegation in order to get a privileged service ticket to the local machine. And then we'll use that service ticket to authenticate to the local service manager and create a new service, such as in NT/System.
I was sitting at home one day, and I was thinking about how we could take KrbRelayUp to the next level. It's already well known that KrbRelayUp will work across the cloud. So if you've got VMs that are in Azure, but you've got on-premise domain controllers, they're still susceptible to KrbRelayUp if you're not using LDAP channel binding and you don't have EPA in place.
So Charlie Clark actually did some amazing work tracking down what actually happens during Kerberos delegation when you're delegation-- when you're delegating from one trust-- from one domain to another domain. So here are laid out the steps for what it looks like when you're in either a child or a parent domain, and you are delegating from one to the other. They're written out here, as well.
But it basically works really similar to how normal constrained delegation works. There's just a couple of extra steps that happen. After you do your standard TGT receipt, then you're going to request a service ticket for the foreign domain controller. And then you go through the S4U2Self with the foreign domain controller. Then you do an S4U2Self with your local domain controller, and then you can use that service ticket in order to actually request a service ticket to the target resource from your local domain controller using that service ticket from the foreign domain controller.
It's a mouthful. It is a bit hard to follow. That's why I've got both the graph here for you as to exactly what happens in those steps, as well as the steps laid out here. If you want more information on how this works and this attack, the link is there right below. Very cool. It does lead to remote code execution from a child to a parent-- to a parent domain.
Why is that such a big deal? Why does that matter? The reason why this matters is because a lot of times, especially when you're seeing parent domains and child domains, you may have a very locked down prod domain. You've made sure that you set your machine account quota to 0. You've really locked down a lot of things that are in place.
However, maybe you've got a development child domain that's there that your devs run around in, and they build different solutions in. And maybe that is less secure. Using that less secure domain, we potentially can move laterally and escalate privileges into your lockdown domain. So in the words of Thomas Reid, a chain is no stronger than its weakest link.
So that's kind of the vulnerability is between trusts. So now let's talk about some of the attack vectors for delegation in a Hybrid AD environment. And in this one, we're saying Hybrid AD environment. I'm talking about both true Hybrid Active Directory, Hybrid join, as well. So regardless if you're using Active Directory, Azure Active Directory Connect, or Azure Active Directory cloud sync, or maybe you just have an Azure tenant that's got some VMs, but they are hybrid joined to domain controllers on premise.
They are still susceptible to KrbRelayUp and other Kerberos-constrained delegation attack methods. Because of this hybrid environment, roles in Azure work a bit different than groups on premise. So it is best practice for all of your privileged roles in Azure to solely live in Azure, and if you have an admin that needs to access one of those roles, they need to log in directly into Azure as that privileged role and not be some account that's on premise-- let's say, some domain admin-- that also sinks into Azure as a privileged role, because that would definitely be an attack-- that would definitely be an attack vector and a target for attackers in your on-prem environment, which would allow them to then move into a very high privileged role in your Azure environment.
Two of the roles that we look to try to exploit in this manner are Azure Global Administrator, as well as Intune Administrator. Those two roles especially have high privileges, including the ability to run scripts as system on any Azure AD or Hybrid join device. So that's both your VMs that live in Azure, as well as physical devices that you're managing with Intune in a Hybrid join.
Another place that I found quite interesting and I've been looking a bit into is the Application Proxy. So the Application Proxy is put in place-- it's a one way proxy that allows for access to on-premise applications from anywhere in the world, like through the internet via your Azure AD.
Now, the Azure AD side of it seems like it's pretty locked down. It's one way. It uses your standard authentication methods with Azure, and it uses the STS engine.
But in order for it to actually communicate with the apps that you have on prem, there's another piece that's in place. So applications typically come in two different forms. You've got modern apps, and you've got legacy apps. Modern apps use modern authentication methods, such as OAuth.
But for this presentation, we're going to focus on legacy apps that are on prem that you are using this application proxy in order to secure. In order for authentication to happen with legacy applications, a lot of times integrated Windows authentication has to be in place. So this Azure AD application proxy will connect back to a proxy connector.
That proxy connector has to be configured with constrained delegation so that it can impersonate users and receive tokens on their behalf when connecting to these legacy apps. So this application proxy connector is definitely a prime target in your environment, and it should be locked down and secured the same way that you would with a domain controller.
Now that we've talked about how we can move from on prem to the cloud, from the cloud to on prem, how we can move across from child domains to parent domains, and parent domains to child domains, and move within domains locally, all within using Kerberos delegation, and by being able to create this special computer that has resource-based constraint delegation in place, what can we do to mitigate this?
First and foremost, one of the first things that I suggest to all of our customers is that you want to enable LDAP signing and channel binding. LDAP signing adds a special signature from the domain controller, and so no relays can happen. It makes it pretty much impossible to do a relay because you'll be able to tell that there is a person in the middle that's sitting there because the signatures won't match.
Channel binding kind of takes that a step farther, and it ties to different layers of the network stacked together. So it's going to tie that transport layer, as well as the network layer together, which creates kind of a unique fingerprint. So if anything happens, even on the networking side, to change that session, that fingerprint won't match, and the session will be killed.
If you're using Active Directory certificate services, you want to make sure that you enable the extended protection for authentication. EPA is essentially channel binding for certificate services. Now, why this is especially important is there's a lot of certificate attack methods that are out there right now. PetitPotam is a big one.
There's quite a few, and what makes certificate attacks a bit different than your standard password attacks are let's say an account has been compromised. The account also has a certificate that it uses for authentication, and the attacker was able to compromise both the certificate and the password, but all you know is that the password has been compromised. So you change the password. Maybe you make a very hard password so that password cannot be used again. You've locked out the attacker.
But you haven't. Changing the password has nothing to do with the certificate. No matter how many times you change the password, that certificate is still valid. A new certificate would still need to be issued out to that client in order to properly secure it.
Moving on, you want to make sure that you set the machine account quota to 0. The only people typically in most environments that need to be able to create machine objects inside of Active Directory are admins, are your domain admins. And they can do that by default with their permissions.
Again, out of the box, this machine account quota is set to 10. So that means that every standard user has the ability, by default, to create and join 10 machines to Active Directory. Microsoft Defender for Endpoint, as well as Microsoft Defender for Identity, they have added in a lot of different features recently to look for a lot of suspicious LDAP behavior, looking for resource-based constrained delegation that has been added to newly created computer devices.
It can detect for KrbRelayUp, as well as other constrained delegation attacks, as well as unconstrained delegation attacks such as printer bug and things like that. Now, you can configure just about any SIEM or SOAR as well to monitor for these activities. It's pretty easy to tell that something weird is going on because the LDAP queries won't look right. They'll have blank fields.
And there's a certain pattern that happens. Especially with KrbRelayUp, you'll see that machine creation. You'll see the resource-based constrained delegation followed behind that. You'll see the relay to the domain controller. So pretty easy to create an alert around those activities.
I do want to give a special thanks out to Charlie Clark, Will Schroeder, Elad Shamir, Benjamin Delpy, Sean Metcalf, Andy Robbins, Dors Davidovich. They've done a lot of research around delegations and a lot of research around Kerberos delegation specifically. And that's what I'm basing my research on and expanding on, so just wanted to give a special thanks to those guys.
During the presentation, if you have any questions, be sure to submit them via the chat. I will be answering them live during the presentation.