Using PowerShell to Monitor Admin Groups for Rogue Accounts

Admit it, it's happened to you! The moment of confusion when an admin group is modified and some old/strange/unknown/misplaced account is spotted. How long has that account been there? What was this for? Did that end-user realize they could do anything they wanted? 😫

Two-thirds of insider threats abuse loose administrative privileges in order to illegitimately access critical systems. In a security report from 2017, 94% of reported beaches could've been thwarted if the local admin group been locked down only to legit admin accounts. One of the essential principles of hacking is Privilege Escalation. Loosely guarded admin groups leave a massive surface for attackers to exploit.

The best practice is to remove admin rights from ALL end-user accounts. Sysadmins should have a regular user account and an administrator account.

How to scare a CSIO.
How to scare a CSIO.

If there should only be a few accounts in the Domain Admins and the local Administrators group, then this is actually really easy to monitor (and enforce).

Using PowerShell to find rogue accounts

There are two PowerShell commands that will report on the admin group memberships. For Active Directory:

PS C:\> Get-ADGroupMember -Identity "Domain Admins" | Select-Object -ExpandProperty SamAccountName

And for local Administrators:

PS C:\> Get-LocalGroupMember -Group "Administrators" | Select-Object -ExpandProperty Name
Domain\Domain Admins

Now let's put together a script that will leverage this information and compare the accounts with a list of trusted accounts that are allowed to exist. The first thing to do is define all the account names that are designated as official admin accounts. We have two lists here because the list of domain admins is going to be different from the list of local admins. (Wildcards are accepted).

#Enter the list of approved admin accounts.  Wildcards are acceptable "*"

#Domain admin accounts
$domainAdminsList = "administrator", "AdminBrian", "AdminSara"

#Local admin accounts
$localAdminsList = "*Domain Admins*", "*administrator"

Next we will check if the device is a domain controller, and if so the commands for checking AD Domain Admins will be used. If not, then the local Administrator group will be checked.

# Check if the device is a domain controller, and if so check Active Directory "Domain Admins"
$domainController = (Get-WmiObject -Query "SELECT * FROM Win32_ComputerSystem").DomainRole -in 4, 5
if ($domainController) {
    # Import the Active Directory module
    Import-Module ActiveDirectory

    # Get the members of the "Domain Admins" group
    $actualAdmins = Get-ADGroupMember -Identity "Domain Admins" | Select-Object -ExpandProperty SamAccountName
    $adminsList = $domainAdminsList
    $accountType = "Domain"    
else {
    # This device is not a domain controller. Check local accounts
    $actualAdmins = Get-LocalGroupMember -Group "Administrators" | Select-Object -ExpandProperty Name
    $adminsList = $localAdminsList
    $accountType = "Local"

Next, the trust list and the list of accounts pulled from the admin group are compared with each other. All the "bad" accounts are stored in $badAdmins.

#Compare the admin accounts vs the adminsList, and if an account exists then add it to $badAdmins
$actualAdmins | ForEach-Object {
    $adminName = $_
    $matchFound = $false
    foreach ($account in $adminsList) {
        if ($adminName -like $account) {
            $matchFound = $true
    if (-not $matchFound) {
        $badAdmins += $adminName
    else {
        $goodAdmins += $adminName

If an account is found in the admins group that is not in the trust list, then alert and report on which account has been discovered. Notice that in the output for the bad admins message, that the keyword "ALERT" is present. We'll use that in Level to trigger an alert.

if ($badAdmins.count -gt 0) {
    Write-Output "ALERT: The $accountType Admins group contains non-standard accounts!"
    exit 1
else {
    Write-Output "Good news!  The $accountType Admins group only contains these approved users:"

This script is on our community script repo here.

Bring it all together with Level

Now that we have a working script, head over to Level and go to Scripts -> Create Script. And paste the contents into the script editor and give the script a useful name and description.

PowerShell script in Level.
PowerShell script in Level.

Next go to Policies and create a new monitor policy (or edit an existing). Then add a monitor to the policy and give it a name (the name shows up in a triggered alert). Chose the type "Run Script" and then select the script that was just created. In the Script Output choose "Contains" and in the Value type "ALERT".

Monitor for detecting rogue admin accounts.
Monitor for detecting rogue admin accounts.

Now that the monitor policy is in place, Level will alert you if there is an exception to the list of trusted admins. If someone were to elevate any other user account outside of the trust list, then you will know about it and can react appropriately.

Spotted you, "Tester"!
Spotted you, "Tester"!

As a closing thought, an additional step that can be taken would be to create a remediation script that would auto-remove any new rogue accounts from the admin groups. Then the response would be immediate and automated, which will ensure that your organization always closes the door on one of the the simplest vulnerabilities!

Have an idea for a script? Please let us know, or contribute on our community script repo:

Sign up for our newsletter

Get our latest articles and our most exciting updates delivered straight to your inbox.

Get started with Level today.

Don't be left behind, join us on a higher level. Contact us for more information and a demo.