Active Directory persistence through userAccountControl manipulation

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:

Figure 1 – Part of the userAccountControl section of the MS-SAMR specification

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.

Investigating the Behavior

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).

Figure 2 – Showing before and after changing the userAccountControl value on a normal computer account

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.

Figure 3 – Showing before and after changing the userAccountControl value again on a normal computer account

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.

Researching Required Privileges

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.

Figure 4 – Testing with “bob”, an unprivileged user

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.

Figure 5 – The DS-Install-Replica permissions is required to set the UF_SERVER_TRUST_ACCOUNT bit

We granted our non-privileged user this permission and attempted our test again.

Figure 6 – Our non-privileged user is granted the DS-Install-Replica permission on the domain object
Figure 7 – Testing again with our non-privileged user

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.

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:

  1. Create a fake computer, MSA, or gMSA account. An existing account can also be used, but the effectiveness of the persistence mechanism will be limited by the frequency of password changes. Though, an existing but stale (no longer used) computer account could be an attractive target.
  2. Grant the “Add/remove replica in domain” privilege to a compromised regular user, group, or well-known entity. We used “Authenticated Users” so that an adversary could compromise any regular user account and regain domain dominance.
  3. Grant the “Write userAccountControl” privilege on the computer object to the same entity as in the above step.

Creating a Computer Account with a known Password

It seems obvious, but not everyone may be familiar with the ability to create a computer account with a known password using the New-ADComputer or the New-ADServiceAccount cmdlets, for example:

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.

Regaining Domain Dominance

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.

Automating the Technique

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.

Figure 8 – Running Add-ServerUntrustAccount

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).

Figure 9 – Running Invoke-ServerUntrustAccount and regaining domain dominance

Mechanism Discovery and Exploitation Detection

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 Exploitation

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.

Figure 10 – Example content of Event Id 4742 indicating exploitation of this method

Wrapping up

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.

Leave a Reply

Your email address will not be published. Required fields are marked *





© 2020 Stealthbits Technologies, Inc.

Start a Free Stealthbits Trial!

No risk. No obligation.