Use PowerShell to Search Active Directory for High-Privileged Accounts


Summary: Microsoft PFE, Ian Farr, provides a Windows PowerShell function that searches for Active Directory users with high-privileged memberships.

Microsoft Scripting Guy, Ed Wilson, is here. Today, we have another guest blog post from Microsoft premier field engineer (PFE), Ian Farr. Take it away, Ian…

As a youngster, I loved watching Columbo, the bumbling, disheveled, and tenacious LAPD detective. At the end of each episode, almost as an afterthought, he’d outwit the murderer with an investigative coup de grace. Televisual gold!

A few months ago, I discussed a function that analyzes the authentication of read-only domain controllers (RODCs). It reports on accounts authenticated by an RODC that aren’t "revealed,"—that is, the account password or secret is not stored on the RODC. For the full write up, see Use PowerShell to Work with RODC Accounts.

At the end of that post, I promised more code to analyze the output of the Get-ADRodcAuthenticatedNotRevealed function. Today, I deliver on that promise with my own nod to Columbo: This post might appear as an afterthought, but it’s not.

First, some background. The Password Replication Policy Administration guidance suggests:

“Periodically, you should review whose accounts have tried to authenticate to an RODC. This information can help you plan updates that you intend to make to the existing Password Replication Policy. For example, look at which user and computer accounts have tried to authenticate to an RODC so that you can add those accounts to the Allowed List. After their credentials are cached on the RODC, the accounts can be authenticated by the RODC in the branch office when the wide area network (WAN) to the hub site is offline.”

The output of the Get-ADRodcAuthenticatedNotRevealed function facilitates a "periodic review" process. For those accounts that are authenticated, but not revealed, you can decide if there is a case to add user and computer accounts to the Allowed list. Conversely, you can analyze the output with the aid of today’s function (Test-ADUserHighPrivilegeGroupMembership) to see if any high privileged accounts have been authenticated by the RODC.

So why check for the authentication of high-privileged accounts?

As a conscientious and competent administrator, you ensure that passwords for a specific set of users and computers are replicated to the local database on corresponding RODCs. You’re happy that passwords for high-privileged users (for example, members of Domain Admins) are not replicated (which is the default configuration). You periodically check the authenticated, but not revealed, output for candidates to add to the Allowed list.

During the latest check, you spot that a certain RODC has authenticated a high-privileged user. Not an issue, you think, because you know the password won’t be stored in the RODC’s local database. Well, consider this…

When a high-privileged user is authenticated, that user’s credentials will be in the memory. If the RODC is compromised, those credentials will be available for the bad guys to use. Given that RODCs in place to address concerns about physical and network security… well, you get the picture!

Enter PowerShell, stage left

I've updated the Get-ADRodcAuthenticatedNotRevealed function to include a –UsersOnly switch. This outputs user objects that are authenticated and not revealed. These objects can then be piped to Test-ADUserHighPrivilegeGroupMembership.

Get-ADRodcAuthenticatedNotRevealed -Rodc HALORODC01 -UsersOnly |
Test-ADUserHighPrivilegeGroupMembership

Here is some sample output:

Image of command output

The Test-ADUserHighPrivilegeGroupMembership function takes an AD user as input and enumerates their MemberOf attribute. MemberOf contains backlinks to the groups that the user is, well, a member of.

$Groups = (Get-ADUser -Identity $User -Property MemberOf).MemberOf

Next, the Switch statement is used to enumerate through the groups and test each iteration against a number of conditions. These conditions are our high-privileged groups, which are represented by the start of their distinguished name and a wildcard character. Here’s what the Switch statement and the first condition look like:

Switch -Wildcard ($Groups) {           

            #Search for membership of Account Operators

            "CN=Account Operators,CN=BuiltIn*" {              

                 #Capture membership in a custom object and add to an array

                [Array]$Privs += [PSCustomObject]@{

                    User = $User

                    MemberOf =$Switch.Current

                }   #End of $Privs

            }   #End of "CN=Account Operators,CN=BuiltIn*"

The –Wildcard parameter lets me specify a condition present in all domains.

            "CN=Account Operators,CN=BuiltIn*"

Account operators? Highly privileged? Well, for starters, they can log on to and shut down domain controllers!

If this is matched by a value in the MemberOf attribute, information is added to an array in the form of a PSCustomObject. This object contains the user information and also the high privileged group information.

User = $User

MemberOf =$Switch.Current

$Switch.Current represents the current object in the loop. Man, I love the Switch statement!

The other high-privileged groups that are tested for are:

  • BUILTIN\Administrators
  • Backup operators
  • Cert publishers
  • Domain admins
  • Enterprise admins
  • Print operators
  • Schema admins
  • Server operators

After all the MemberOf values are processed, the $Privs array is returned. End of function.

Here’s how to test every RODC in the domain for high-privileged authentication that’s not revealed.

Get-ADDomainController -Filter {IsReadOnly -eq $True} |

Get-ADRodcAuthenticatedNotRevealed -UsersOnly |

Test-ADUserHighPrivilegeGroupMembership

Next time, I’ll talk about using Windows PowerShell to delegate RODC administration.

Ah, yes…in the words of Lt. Columbo, “Just one more thing...” I advise checking that the protected user (Administrator) hasn’t been authenticated:

Get-ADDomainController -Filter {IsReadOnly -eq $True} |

Get-ADRodcAuthenticatedNotRevealed -UsersOnly |

Where-Object {$_.SID -like "S-1-5-21-*-500"}

Here, we filter the output of the Get-ADRodcAuthenticatedNotRevealed function for the well-known security identifiers (SIDs) of the Administrator account. The wildcard character replaces the domain portion of the SID. 

The complete function is located in the Script Center Repository: Test-ADUserHighPrivilegeGroupMembership.

~Ian

Thank you, Ian, for another wonderful post and for a great function.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Comments (0)

Skip to main content