Last month, Elad Shamir released a phenomenal, in depth post on abusing resource-based constrained delegation (RBCD) in Active Directory. One of the big points he discusses is that if the TrustedToAuthForDelegation UserAccountControl flag is not set, the S4U2self process will still work but the resulting TGS is not FORWARDABLE. This resulting service ticket will fail for traditional constrained delegation, but will still work in the S4U2proxy process for resource-based constrained delegation.
Does the first paragraph sound like Greek? Check out these resources so it makes it bit more sense:
- Matan Hart’s BlackHat Asia 2017 “Delegate to the Top” talk and whitepaper.
- The “S4U2Pwnage” post for background on traditional constrained delegation, including S4U2self/S4U2proxy.
- Ben Campbell’s “Trust? Years to earn, seconds to break” for another perspective on the same topic.
- CyberArk’s “Weakness Within: Kerberos Delegation” post on constrained delegation
- The “Another Word on Delegation” on the start of some of the resource-based constrained delegation (RBCD) material.
- Elad’s “Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory” for a complete set of details on his new RBCD research. Seriously, go read it.
Why care? That’s what I hope to show in this post with a practical example, instead of doing my normal dive-into-insane-depth-on-a-topic thing.
The tl;dr is that Elad’s new research gives us a generalized DACL-based computer takeover primitive (among other things, however I’m focusing just on this example for now). This means that if we have an ACE entry allowing us the ability to somehow modify a specific field for a computer object in Active Directory (specifically msDS-AllowedToActOnBehalfOfOtherIdentity, so rights would include GenericAll, GenericWrite, WriteOwner, etc.) we can abuse this access and a modified S4U Kerberos ticket request process to compromise the computer itself.
Note: if DACLs, ACEs, and “object takeover” sounds like another dialect of Greek to you, check out Andy Robbins’ and my “Ace Up the Sleeve” talk and associated whitepaper for more security-focused DACL discussion. For another take on the subject, check out the “The Unintended Risks of Trusting Active Directory” talk that Lee Christensen, Matt Nelson, and myself gave at DerbyCon 2018.
The tl;dr of the tl;dr is that if we can modify a computer object in Active Directory, we can compromise the computer itself in modern domains.
There’s one caveat: the domain the computer resides in has to have at least one 2012+ domain controller in order to support the resource-based constrained delegation abuse. If this isn’t the case, and the domain only has domain controllers with Server 2008 (an 11 year old operating system) there are probably other issues you can target for abuse : )
Taking over a Computer Object Through Resource-Based Constrained Delegation
I’m not going to explain resource-based constrained delegation in depth as the resources at the start of this post have all the information you need. Instead, I’m going to walk through a practical abuse example with syntax and screenshots illustrating the abuse so you can get a feel for how it works operationally. This scenario is fairly similar to the “Another Word on Delegation” post I published last year, as well as the “Generic DACL Abuse” section of Elad’s post. That is, there’s nothing new here, Elad covered everything in awesome depth with a ton of details and videos. I wanted to present a slightly different practical demonstration with full weaponization details in order to bring attention to his awesome research.
My test environment will be my standard Windows Server 2012R2 domain controller with a 2012R2 domain functional level, and Windows 10 host:
- The domain is testlab.local with domain functional level 2012R2.
- The domain controller is primary.testlab.local, and is 2012R2.
- The client is Windows 10.
- The TESTLAB\attacker user account has GenericWrite access to the PRIMARY$ computer object, but has no other special privileges nor rights.
- The tools used are PowerView, Kevin Robertson’s Powermad (specifically the New-MachineAccount function), and Rubeus’ S4U command.
- A text transcript of this scenario is available here.
First we’re going to load up our toolsets, confirm our identity, and verify that our current user has the proper DACL misconfiguration to allow abuse. Using PowerView to enumerate the specific ACE in the access control information for our target system (primary.testlab.local), we can see that we (TESTLAB\attacker) have GenericWrite over the PRIMARY$ computer object in Active Directory. The relevant syntax for these commands are here.
As Elad details in his post, we need control of an account with a service principal name (SPN) set in order to weaponize the S4U2self/S4U2proxy process with resource-based constrained delegation. If we don’t have preexisting control of such an object, we can create a new computer object that will have default SPNs set. This is possible because MachineAccountQuota is set to 10 by default in domains, meaning that regular domains users can create up to ten new machine accounts.
The msDS-AllowedToActOnBehalfOfOtherIdentity field is an array of bytes representing a security descriptor. I couldn’t quite figure out all of the nuances of its structure, so I used the “official” way to add resource-based constrained delegation in my test lab, extracted the msDS-AllowedToActOnBehalfOfOtherIdentity field and converted it to SDDL form. From this template, we can easily substitute in the SID of the newly created computer account that we control (which has a SPN!), convert it back to binary form, and store it into the msDS-AllowedToActOnBehalfOfOtherIdentity field of the computer object we’re taking over using PowerView. The relevant syntax for these commands are here.
Let’s double check that the security descriptor added correctly. We can see below that the SecurityIdentifier in the entry states that the computer account attackersystem$ has “AccessAllowed”. The relevant syntax for these commands are here.
Let’s review: we’ve modified a special property of our target computer object (primary.testlab.local) to state that a computer account (TESTLAB\attackersystem$) is allowed to pretend to be anyone in the domain to the primary computer. Since we have the password of attackersystem$ (as we created it, again abusing MachineAccountQuota), we can authenticate as attackersystem$ and abuse the resource-constrained delegation process to compromise primary.testlab.local!
In this case, we’re targeting the service name (sname) of cifs, the service that backs file system access. First let’s prove we don’t have access, and then get the RC4_HMAC hashed version of the password. Relevant syntax here.
And thanks to Elad’s additions, we can execute this with a single Rubeus command. Relevant syntax here.
Since PRIMARY$ is a domain controller, and the ldap service name backs the DCSync process, all we have to do is change the /msdsspn parameter from cifs/primary.testlab.local to ldap/primary.testlab.local if we wanted to DCSync instead We can execute this for any service name (sname) we’d like to abuse.
Once we’re done abusing the scenario, we can clean up with PowerView as well.
Elad’s post is one of the best that I’ve read in a long time. It’s filled with a ton of information and abuse scenarios that we’ll unpacking for a while as an industry. I strongly strongly recommend anyone who’s interested in these topics to start digesting Elad’s post- you’ll be that much better for it.
I wanted to illustrate another example in this post to show how his research can be practically applied. We’re also in the process of updating the BloodHound schema, and hope to integrate these DACL based computer takeover primitives soon!