I’ve been doing some research on group Managed Service Accounts (gMSAs) recently and reading the MS-SAMR protocol specification for some information. I happened to stumble across some interesting information in the userAccountControl section which made us drop what we were doing to test it:
Effectively, when the UF_SERVER_TRUST_ACCOUNT bit is set in the userAccountControl attribute of a computer object then Active Directory must set the same object’s primaryGroupId to the RID of the Domain Controllers group. Therefore, simply changing userAccountControl can grant a computer object the privileges of a domain controller.
We started testing using a Domain Admin account in our lab and first attempted to use the default userAccountControl value for a domain controller of 0x82000 (decimal 532480), which is the sum of bit flags for SERVER_TRUST_ACCOUNT (0x2000, decimal 8192) and TRUSTED_FOR_DELEGATION (0x80000, decimal 524288).
After changing the userAccountControl value, we see that the primaryGroupId is updated to 516 (the RID for the Domain Controllers group) and we’re off to a great start! Next, we wanted to know if only the SERVER_TRUST_ACCOUNT bit is required, so we attempted again setting the userAccountControl attribute to 8192.
We’ve thus confirmed the accuracy of the protocol specification, and that it is only the SERVER_TRUST_ACCOUNT bit that causes the primaryGroupId to change.
We begin to consider possible vectors of abuse. If only the ability to modify the userAccountControl attribute is required, then we could be on to an interesting privilege escalation technique. We started testing with an unprivileged account with only permissions to modify the userAccountControl attribute and quickly encountered access denied errors.
Turns out that we should have read just a few more lines down in the MS-SAMR documentation. Section 5 of the userAccountControl attribute outlines additional permissions required to set certain userAccountControl bits. In order to set the userAccountControl UF_SERVER_TRUST_ACCOUNT bit, the actor must have the DS-Install-Replica (“Add/remove replica in domain”) permission granted on the domain object.
We granted our non-privileged user this permission and attempted our test again.
After granting the write userAccountControl privilege on the computer and the DS-Install-Replica privilege on the domain object to our non-privileged user, our test was successful.
By default, the DS-Install-Replica permission is granted to the groups “Domain Admins” and “Enterprise Admins.” Thus, in all but poorly configured environments this approach does not represent a privilege escalation vector. However, given the limited permissions required we began to think of applications for domain persistence.
In evaluating whether this presents an interesting method for persistence, we considered several factors: that a limited set of privileges are required, that these privileges are not commonly reviewed, that (objectClass=computer) accounts are easy to create, that computers are infrequently reviewed (many organizations struggle with stale computer objects), and that exploitation of the mechanism is easy and signs short-lived.
Configuring this mechanism only requires a few small steps:
New-ADComputer “ComputerName” -AccountPassword (ConvertTo-SecureString -AsPlainText -Force “Password”)
Knowing the plaintext password is beneficial for a few reasons. Most importantly, we can compute the NTLM, AES-128, and AES-256 hashes using the ConvertTo-NTHash and ConvertTo-KerberosKey cmdlets of Michael Grafnetter’s DSInternals PowerShell module. When the adversary chooses to exploit the backdoor, they’ll need to authenticate as the computer account to use its privileges and will do so with the overpass-the-hash technique. Specifying the NTLM and AES hashes evades most overpass-the-hash detections.
After staging the account and permissions, if the adversary loses access to their administrative credentials or is evicted from the network, they only need to compromise any regular user to regain domain dominance.
With any user account, the adversary only needs to modify the userAccountControl attribute of their staged computer to 0x2000 (8192). This modification also causes an immediate replication, which means that the adversary does not need to target specific domain controllers. Once the userAccountControl is complete, the adversary can use their domain controller privileges to compromise the domain.
For example, the adversary could use the computer account to perform DCSync and compromise the krbtgt password hash. Because the replication appears to be coming from a domain controller, most DCSync threat detections do not detect the activity. Once they’ve replicated the krbtgt secret, they can simply flip userAccountControl back to 0x1000 (4096) and the computer account will appear as a normal computer account.
To help demonstrate the potential effectiveness of this method, I created two new PowerShell functions that are available on GitHub.
The first function, Add-ServerUntrustAccount, automates the three setup steps – creating a fake computer account with a known password and granting “Authenticated Users” the “Add/remove replica in domain” and “Write userAccountControl” privileges.
The second function, Invoke-ServerUntrustAccount, automates the exploitation of the backdoor and is intended to be run as a non-privileged user. The function sets the userAccountControl attribute to 0x2000 (8192), then uses pass-the-hash to authenticate as the fake computer account, performs a DCSync of the krbtgt hashes, and finally sets userAccountControl back to 0x1000 (4096).
To find this and other similar mechanisms, organizations should be auditing sensitive Active Directory permissions periodically. Monitoring (or even blocking) sensitive permissions changes (like the “Add/remove replica in domain”) in real-time is also beneficial. We tested several popular open-source Active Directory permission auditing tools, and only AD ACL Scanner correctly highlights our adversary’s permissions as troubling.
Active Directory event logs – namely Event IDs 5136 and 4662 – provide for basic real-time monitoring of ACL changes and can be used to detect the domain-level “Add/remove replica in domain” privilege. However, the process of analyzing these events is not straightforward.
Additionally, finding and removing computer (and MSA and gMSA) accounts that are stale, or don’t match an actual machine on the network is important. For example, you can quickly find stale or unused computer accounts with PowerShell (replacing “-90” with your domain’s maximum computer account age):
$Date = [DateTime]::Today.AddDays(-90); Get-ADComputer -Filter ‘(Enabled -eq $true) -and (PasswordLastSet -le $Date)’ | Select Name
Detecting an adversary’s use of this technique revolves around monitoring for changes to the userAccountControl attribute. Event Id 4742 – Computer Account Management can be used to monitor for changes to userAccountControl values. Any modification of userAccountControl with the bit 0x2000 set outside of an expected domain controller promotion is troubling.
While obviously not as serious as a critical vulnerability, these kinds of techniques frequently go undetected in enterprises and can make an incident responder’s job even harder. Given the low detection rate in the Active Directory auditing tools we tested, we think this is an interesting technique that abuses lesser-known behavior that could easily be missed. We welcome your comments and questions, and we’d be remiss if we didn’t point you over to our Attack Catalog, where you can learn more about how certain attacks work.
Start a Free Stealthbits Trial!
No risk. No obligation.