How to Become a DC Through Creative Replica
I recently came across the DS-Install-Replica permission on a domain object and admittedly didn't know its function. I wanted to explore this further from an offensive perspective and understand how it could be abused if applied incorrectly in a domain. In this write-up, I will configure a group in my AD lab to have the Add/remove replica permission and demonstrate how this privilege, when chained with machine account quota, can be used for domain compromise.
This is not an original idea on my part. I want to shout out Stealthbits for their excellent write-up about this very permission and how it can be abused and then used for persistence. Their article helped me understand the extent of how this can be abused and the how behind it. My approach to the topic is a bit different as I wanted to explore how it can be used for domain compromise rather than for persistence. My perspective is based on my understanding of permission and AD's default configuration. It's very common for over-permissive rights to be granted through access control lists and DS-Install-Replica is no different.
The Basics
I have a domain called DUNDER.local with two computers running. You can probably tell by the naming schema of the lab that I am a fan of The Office π
- DUNDERDC01 - Windows Server 2022 playing the role of the domain controller
- DUNDERWS01 - A Windows 10 client joined to the domain
- Jim Halpert - Standard user, not privileged in the domain. Is a member of the Workstation Admins security group.
Before we begin, I want to mention the following, just to get it out of the way:
- DUNDERWS01 has RSAT installed via optional features. This enables the Active Directory module in Powershell.
- Defender is disabled on DUNDERWS01. By disabling Defender, tools such as Mimikatz and Rubeus aren't blocked from running. I am trying to prove a concept with this write-up without the worry of trying to evade AV.
What's the Deal?
In short, if a security principal has been granted the DS-Install-Replica (Add/remove replica in domain) permission, they can modify the userAccountControl attribute of a computer object in a way that changes the primaryGroupID to the RID of the domain controllers group (RID 516). This is interesting because it automatically promotes a computer object to a domain controller, enabling replication. Pretty neat, huh?
Specifically, DS-Install-Replica rights are required to set the userAccountAttribute value to 8192, which represents the bits for SERVER_TRUST_ACCOUNT. This value designates a computer object as a domain controller in the domain. There are certain values that cannot be set without additional rights, and this is one of them.
If you want the technical information behind this, I suggest you check out the deep-dive on Stealthbits's Server (Un)Trust Account article.
So what does this mean for us? Well, if you can identify a user or group that has been granted DS-Install-Replica (Add/remove replica in domain) rights on the domain (misconfigurations are all too common), and combine it with the fact that any authenticated user can add up to 10 computer objects to the domain by default, it creates a privilege escalation vector that can lead to a DCSync attack vector.
The Demo
Checking MAQ
First, let's confirm we can add computer objects to the domain as a low-privileged user. By default, authenticated users can add up to 10 computer objects to the domain. This is referred to as the MachineAccountQuota, or MAQ for short. In the DUNDER domain, it is set to the default as well.
Get-ADDomain | Get-ADObject -Properties ms-DS-MachineAccountQuota | select name,ms-DS-MachineAccountQuota
Just because the ms-DS-MachineAccountQuota value is set to a non-zero number does not mean we can add computer objects to the domain. Let's verify the default domain controller policy to check what it allows. In our case, NT AUTHORITY\Authenticated Users are allowed to add workstations to the domain, which is perfect!
Creating Machine Account with StandIn
As we can add computers to the domain, we will use StandIn to automate the creation of a computer object with a known password. This will be helpful later on when we need to assume the context of the machine account. For this demonstration, I chose to name the computer DUNDERDEMO
.
. C:\Tools\StandIn_v13_Net35_45\StandIn_v13_Net45.exe --computer DUNDERDEMO --make
If we check in ADUC, we see the new computer object was in fact created and appears in the Computers container.
Verifying Current UAC
Let's check the current userAccountControl and primaryGroupId attributes of the computer we just created. As expected, the UAC value represents the bits for WORKSTATION_TRUST_ACCOUNT (4096), along with the primaryGroupId of Domain Computers (RID 515).
Get-ADComputer dunderdemo -Properties userAccountControl,primaryGroupId | select name,userAccountControl,primaryGroupId
It doesn't work
Can we simply set the userAccountControl attribute to SERVER_TRUST_ACCOUNT (8192), and we're done? That would be too easy, right? Unfortunately, no. To set these bits, you need to have DS-Install-Replica (Add/remove replica in domain) rights granted on the domain object.
Set-ADComputer dunderdemo -Replace @{"userAccountControl" = 8192}
Suppose that through some enumeration, you discovered that Workstation Admins has an access control entry on the domain object that grants the Add/remove replica in domain permission. Will this work?
Let's also say you have compromised Jim's account and noticed he's in the Workstation Admins group. What does this mean? Jim is able to set the userAccountControl attribute to SERVER_TRUST_ACCOUNT (8192).
It works!
With DS-Install-Replica rights granted to Workstation Admins, we can set the userAccountControl attribute to SERVER_TRUST_ACCOUNT. After verifying the primaryGroupId, it is now 516, which represents the RID of the domain controllers group!
Set-ADComputer dunderdemo -Replace @{"userAccountControl" = 8192}
Get-ADComputer dunderdemo -Properties userAccountControl,primaryGroupId | select name,userAccountControl,primaryGroupId
We used the DS-Install-Replica rights granted to the Workstation Admins group to successfully set the userAccountControl attribute of the machine we created using StandIn. As a result, our machine is now a "domain controller".
Let's go do domain controller things now, shall we?
We're A DC Now!
I am going to use Rubeus to create leverage logon type 9 to spawn a new command prompt as DUNDERDEMO$ using createnetonly with the credentials provided when StandIn created the new computer.
. C:\Tools\Rubeus.exe createnetonly /program:"C:\Windows\System32\cmd.exe" /show /username:dunderdemo$ /password:dhl5H7QKWfYFCiE /domain:dunder.local
As we are running under the DUNDERDEMO$ machine account, which is acting as a domain controller, we are now able to DCSync! Let's grab krbtgt for safe keeping π
lsadump::dcsync /user:dunder\krbtgt /domain:dunder.local
Cleaning Up
Now that we have demonstrated how to abuse DS-Install-Replica, let's revert the userAccountControl property of our computer to the original value of 4096. Notice the primaryGroupId changes back to 515 as well.
Set-ADComputer dunderdemo -Replace @{"userAccountControl" = 4096}
Get-ADComputer dunderdemo -Properties userAccountControl,primaryGroupId | select name,userAccountControl,primaryGroupId
If we use Rubeus once more to get a session as the DUNDERDEMO$ machine account and attempt to DCSync again, it fails since we're no longer being treated as a domain controller. That's okay - we already have krbtgt!
That's it!
That's all I have for now. If you're a blue teamer, make sure you're aware of the rights being granted to principals in your domain. Perform audits to ensure that over-permissive rights are removed if they are not justified.
Until next time, take care!