Are Account Operators “All That”?

This blog post is going to be a quick recap of what I’ve recently learned about Account Operators in Active Directory. During one of my recent penetration tests, I was able to compromise a user that was a part of the Account Operators group, which BloodHound kindly marks with a high value diamond icon, but I had not been in a scenario where I had needed to abuse these privileges before, so I went about putting together the steps I’d need to use this account.

Microsoft defines the Account Operators as:

The Account Operators group grants limited account creation privileges to a user. Members of this group can create and modify most types of accounts, including accounts for users, Local groups, and Global groups. Group members can log in locally to domain controllers.

Members of the Account Operators group can’t manage the Administrator user account, the user accounts of administrators, or the Administrators, Server Operators, Account Operators, Backup Operators, or Print Operators groups. Members of this group can’t modify user rights.

There are several blog posts in the top results that I found that gave some statements about how to abuse different group permissions in Active Directory. (I won’t link to these sites for reasons that will become apparent) The example in the screenshot below mentions that Account Operators (AO) can’t modify the big the groups (Domain Admins, Enterprise Admins, and Administrators), but that they can add users to any group nested in one of those three groups. Fairly frequently I run run into groups that have been added to one of the administrative groups, and it was case during this test as well.
screenshot

For good measure, I also asked ChatGPT to sum it up, since it draws from more than just one blog or website. ChatGPT is a great tool to start, but should be used carefully. ChatGPT has made the claim here that an AO could “add themselves or others to high-level groups like Domain Admins”, which contradicts what we see from Microsoft. But what happens in practice? These are the times where you need a lab where you can test with full visibility into the configuration and logs. screenshot

Setting Up The Lab

It seems like whenever I’m reading a blog post that I’m really interested in, they have this magical lab with all these settings that are hidden behind the veil. For that reason, I’ve decided to include the lab details here for anyone wanting to mock this up with me. This scenario is really fast to setup if you already have a domain setup.

  1. A domain controller (Required) - You should have a server setup with Active Directory Domain Services. If you don’t know how to do that, you can follow this guide by Microsoft which covers steps for PowerShell or the GUI
  2. An Account Operator user (Required) - Once you have Active Directory going, create a user from Active Directory Users and Computers and make sure they’re a member of the Account Operators group
  3. An account to move between groups - Just create any account and leave them in the default Domain User group. We’ll use this user to test different scenarios.
  4. A non-domain joined Windows host (Optional) - With nearly all my tests, I have a non-domain joined Windows host that I use, so in order to better simulate a real test, I will typically use a Windows host I have not joined to the network to test things out, that way I know my steps will work in the real world if I don’t have a compromised machine to work from or don’t want to risk running tools on one I do have access to. If you do this, use the runas prompt to open powershell as a domain user. The command is pasted below. If you don’t want to do this, don’t worry, just login to the domain controller as the AO user.
# Powershell command to install RSAT from an administrative prompt
Add-WindowsCapability -online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0

# Runas prompt
runas /netonly /user:[DOMAIN]\[USERNAME] powershell

In my lab setup I will have two users:

  • ao.user - This user is part of the Account Operators group
  • holden - This user will be my example user, in a real test, we’d be using any user under our control if the rules of engagement allowed for it, otherwise we would need a sample user account to test these actions on

Testing Theories

Now that we have our lab ready, let’s look at the different theories we’re going to need to validate. Here are a collection of claims that I’ve collected from some blog posts out there, and of course, the ChatGPT claim that we can add a user to the Domain Admins group.

  1. AO users can add to the Domain Admins group (ChatGPT)
  2. AO users can add to a group nested within one of the administrative groups
  3. AO users can change the password of an administrative user
  4. AO users can change the password of users in a group nested within one of the administrative groups

Adding Users To Domain Administrative Groups

First, let’s test what ChatGPT indicated about an Account Operator being allowed to add users to an administrative group like Domain Admins. We can do that with the net command, but I prefer one of the PowerShell cmdlets because it works on machines both on and off the domain. If you have a machine without RSAT that is domain joined, you could use the net command for this, but that won’t be covered here.

# From a domain joined machine
Add-ADGroupMember -Identity "Domain Admins" -Members [USER TO ADD]

# From a non-domain joined machine using a prompt run as a domain user
Add-ADGroupMember -Server [DC IP/Hostname/FQDN] -Identity "Domain Admins" -Members [USER TO ADD]

When we test that in our lab, we see that, as indicated by Microsoft’s documentation, an Account Operator cannot add a user to one of the domain administrative groups like Domain Admins. screenshot

Modifying Administrative Accounts

Next lets test some of these other theories I’ve seen floating around. Can we modify a user account that is already part of the Domain Admins group? We could achieve this with the RSAT cmdlet Set-ADAccountPassword

# From a domain joined machine
Set-ADAccountPassword -Identity [USER TO MODIFY] -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "CovertCorvus" -Force)

# From a non-domain joined machine using a prompt run as a domain user
Set-ADAccountPassword -Server [DC IP/Hostname/FQDN] -Identity [USER TO MODIFY] -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "CovertCorvus" -Force)

When we try to change the password for the Administrator user in our lab, you’ll notice that it’s not possible. Myth busted? Well… not quite. screenshot

Let’s try that same command on a different user. This user was created by me and has been added to the Domain Admins group roughly 3-4 minutes before the password reset command was attempted. You’ll notice that, although the user is in the Domain Admins group, we are able to change their password. However, if you try this again in screenshot

If we wait about 5-10 minutes, you’ll eventually see the value adminCount on the account set to 1, which means this user is or was at one point domain administrative. Once this value is set, we won’t be able to change the user password anymore from our Account Operator account. This seems to be where a bit of the confusion comes from that I see from some beginner users. They create a new account, add it to domain admins, test a password change, see that it works, and assume it will always work. They don’t realize it’s a very limited window of opportunity. screenshot

So why does this happen? Well, it’s because the Security Descriptor Propagator (SD Propagator) is in charge of detecting users that are in or inherit from domain administrative groups and setting in adminCount to 1, and this process only runs every 60 minutes by default. In my tests, my users regularly had their adminCount incremented within 10 minutes, but I may have just gotten lucky, or there may be another process I’m not aware of that’s doing a more frequent sweep. Either way, we now know that in practical terms, we won’t be able to perform this in a real test as it’s unlikely we will learn about a domain administrative user within 10 minutes of it’s creation and be able to perform the above actions. It’s not impossible, but I’d hate to just be hoping and waiting for that to occur.

Adding Users To Secondary Administrative Groups

We know we can’t add users to one of the administrative groups, but what about a secondary group - a group that inherits from one of the administrative groups? That command will be almost identical to the one we used when we tried to add a user to Domain Admins, but we’ll be substituting it for another group name.

# From a domain joined machine
Add-ADGroupMember -Identity "[SECONDARY GROUP NAME]" -Members [USER TO ADD]

# From a non-domain joined machine using a prompt run as a domain user
Add-ADGroupMember -Server [DC IP/Hostname/FQDN] -Identity "[SECONDARY GROUP NAME]" -Members [USER TO ADD]

In my lab, I’ve just created a group called NestedAdmins that is a part of the Domain Admins group. Let’s try to add a non-administrative user to that group! We can see that, before we start, adminCount on NestedAdmins is null and that we are able to successfully able to add the user holden to this group. screenshot

Now, you’re probably catching on to what I’m leading to about the adminCount. Like users, groups have an adminCount property, and in this case, it is not immediately set on a group when it is added to a domain administrative group. However, given enough time, it will populate. If we remove holden from the group and try to re-add them to NestedAdmins after adminCount is set to 1, we get the same error as we do when trying to modify a user. screenshot

Modifying Users In Secondary Administrative Groups

What about modifying an existing user of one of the secondary groups? Well, let’s test it out! These will be the same commands as when we tried to change the password on an administrative user, but I’ll put them here for ease of use.

# From a domain joined machine
Set-ADAccountPassword -Identity [USER TO MODIFY] -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "CovertCorvus" -Force)

# From a non-domain joined machine using a prompt run as a domain user
Set-ADAccountPassword -Server [DC IP/Hostname/FQDN] -Identity [USER TO MODIFY] -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "CovertCorvus" -Force)

Let’s try to change the password of the user holden, who has been freshly added to a secondary group called NestedAdmins. screenshot

It works! But by now, you know to question if that is going to last. And the answer is, it doesn’t. Once the SD Propagator comes along, the adminCount is set to 1, and users within the group cannot have their password changed. screenshot

Is There Any Value?

I have yet to find a way to go directly from Account Operator to Domain Admin or it’s equivalent, though it is absolutely possible there may be a method I’m unaware of. Still, this isn’t to say a user in this group is worthless. There are plenty of other ways we can use the Account Operator privileges, but you may need to get creative. A few of the methods I plan to use the next time I end up this situation during a penetration test are:

  • Add a user to a group allowed to view LAPS passwords (Then fetch these passwords with something like CrackMapExec!)
  • Add a user to a group with local administrative access to workstations or servers (Then dump LSASS to hopefully get some credentials)
  • Add a user to a group with RDP permissions on workstations or servers (Then access to try to perform a session takeover or hunt for domain privilege escalation points on the host)
  • Add a user to a group with access to HR, finances, or IT (Then show how an attacker could use this method to access sensitive information. Remember, it isn’t always about administrative access!)

This blog post is already longer than I meant to make it, so I won’t go into detail about each of those methods. There are likely plenty of other paths to take, you just have to get creative, which is what pen testing is all about! I love having the opportunity to explore these types ideas and being able to clearly appraise the the value of the various permissions you’ll find assigned to Active Directory users.

Summary

So what did we learn? While Account Operators may not have the ability to manage the most sensitive administrative accounts and groups, their still valuable for getting new permissions that could absolutely be what you need to get domain admin access. We also learned not be believe everything you read (this blog included)! During our lab tests, we were able to validate some of the theories about what an AO can and cannot do, such as adding users to nested groups within the administrative groups. However, it’s important to note that every Active Directory environment is different and may have unique configurations that could affect the privileges and limitations of an AO account.

Ultimately, it’s a great example of why having a lab is important. Even if you know the theory of an attack, putting it into practice is a whole different story. Only by testing the above theories were we able to get the complete story. For me, it helped me understand a little bit more about how AD propagates changes as well. Hopefully you were able to learn something new from this post as well. As always, I’m open to feedback or discussion. Feel free to reach out to me on Twitter or Discord!