Delegate 2 Thyself
Posted on Tue 17 March 2020 in Active Directory
This post is also avaliable in PDF format here.
So a situation arose on the BloodHound Slack channel recently which is very similar to the one I'm going to describe in this post and the user could have benefited from this so I've decided to speed up my writing of this particular post. It's going to involve using resource-based constrained delegation (RBCD) for local privilege escalation.
Firstly, there are much better resources for a full explaination of the RBCD theory and attack vectors, the best I've read Wagging the Dog by Elad Shamir but also this and this by Will Schroeder, and even the Microsoft Kerberos documentation if you are really looking at understanding how Kerberos works as a whole.
I learned everything I know about RBCD from the posts mentioned above, so I highly recommend reading and understanding those if you truly want to understand RBCD.
Here I'll simply be explaining an attack that, while very similar to some being spoken about, I've not really seen anywhere, while trying to clear up a few areas of confusion a lot of people seem to have on the topic.
Resource-Based Constrained Delegation 101
While those other posts are without doubt the place to go if you want to understand how this works, I'll try to give a little recap of the essentials here.
Delegation is used in Kerberos to allow services to delegate (impersonate) as other users to other services. This is so that, for example, if a user access a web server and that web server is using a database server in the background, the web server is able to impersonate the user to access the database server and only gain access to the data owned by that user.
Resource-Based Constrained Delegation is governed by an Access Control List (ACL) contained within the msDS-AllowedToActOnBehalfOfOtherIdentity Active Directory attribute of the target machine account. This means if you want AccountA to be able to delegate to AccountB, then you have to set an Access Control Entry (ACE) within the ACL in the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on AccountB for AccountA.
Confusion 1 - Service Accounts
So as Elad mentions in his post that SYSTEM, NT AUTHORITY\NETWORK SERVICE and Microsoft Virtual Accounts all authenticate on the network as the machine account on domain-joined systems. This is really useful to know as most Windows services on modern versions of Windows will run using a Microsoft Virtual Account by default. The 2 most notable are IIS and MSSQL but I'm sure there are many more.
This can be verified very easily:
This authenticates against 192.168.71.198 where I have impacket's smbserver.py script listening:
In any situation where the machine is domain-joined and you can run code as NT AUTHORITY\NETWORK SERVICE or a Microsoft Virtual Account, you can use RBCD for local privilege escalation, provided that Active directory hasn't been hardered to mitigate the RBCD attacks completely (which is very rarely the case).
The Situation
So here I'm going to perform the attack from a domain-joined (external.zeroday.lab) IIS server (EIIS1) where code execution has already been achieved. As we already know, this account will authenticate on the domain as the machine account:
Firstly, load the the ADModule from Nikhil Mittal and Will Schroeder's PowerView to be used throughout this post:
The last thing to note is a domain admin (and the user we're going to impersonate) is external.admin:
Confusion 2 - Machines Creating Machines
Generally with these RBCD attacks you require a second account with an service principal name (SPN), the common method is to create a new machine account as by default the machine account quota is 10:
I've seen some confusion on whether a machine account can be used to create another machine account. It is possible to create a machine account using a machine account, this can be done using Kevin Robertson's Powermad:
Now querying the domain controller, the newly created machine account can be seen:
The Crazy Bit
For this post though, I want to show that even if the machine account quota is 0, and access to another account with an SPN hasn't been achieved, it's still possible to abuse RBCD for privilege escalation. So the machine account quota has been reset to 0:
Now it is not possible to create a new machine account:
So here's the main reason for this blog, I was thinking one day "I wonder if a machine can delegate access to itself". So effectively, I (the machine account) want to tell the domain controller that I (the machine account) wants the ability to delegate access to myself (the machine account). I'm not sure why this would ever be required in a normal setup, but it in fact is possible.
So using the shell that I've already imported the ADModule, I can set the msDS-AllowedToActOnBehalfOfOtherIdentity:
This is all that is required to configure RBCD. To demonstrate that it has infact worked, I can run Get-ADComputer
from another terminal (because showing the extended attributes using the ADModule doesn't work):
So now I have the ability to impersonate any domain user on the machine, that isn't in the Protected Users group or marked as Sensitive and cannot be delegated.
Abusing This Configuration
There's one more piece of the puzzle before we can actually perform the attack. We need to be able to pass Rubeus credentials for the machine account. This can be in the form of a username and password, or a TGT ticket.
Luckily Benjamin Delpy figured out how to do this, it's now called the tgtdeleg trick and it's also been implemented in Rubeus.
So after downloading Rubeus onto the compromised system, we can easily use it to grab a usable TGT:
That TGT can be used with the s4u Rubeus command to request a service ticket to HTTP/EIIS1.external.zeroday.lab (myself) as the user external.admin and injected into the current context:
Now when we use Invoke-Command to EIIS1.external.zeroday.lab, it runs as external.admin:
Cleanup
When on an assessment, it's always important to clean up any changes made to systems to return them to the original settings as much as possible. The RBCD configuration can be reset to it's original state using the machine account again, if domain admin privileges hasn't been achieved.
If the configuration was originally empty, this can be done in the following way:
And to verify that this worked:
Conclusion
Delegation is hard and often configured wrong so it's important to understand the scope of what is possible using these Kerberos features.
Active Directory in it's default configuration is vulnerable to a number of different attacks and these settings rarely get changed by the system administrator so this is often a very fruitful avenue for an attacker.
To secure AD against this attack is no different to those described by Elad in his post, there's nothing really new here apart from the idea of delegating to the same account.