Notice: Due to size constraints and loading performance considerations, scripts referenced in blog posts are not attached directly. To request access, please complete the following form: Script Request Form Note: A Google account is required to access the form.
Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

Who Watches the Groups? Auditing Elevated Permissions in Active Directory


In many environments — especially those with a long-standing Active Directory implementation — access rights can quietly escalate over time. And sometimes it’s not even malicious. One overlooked but very real problem I encounter regularly is what I call "group membership shopping."

🛍️ Beware of Group Membership Shopping

This happens when users — often admins or overly curious power users — start exploring Active Directory and adding themselves to groups based solely on how interesting or powerful the name sounds. It’s an informal privilege escalation technique that happens not with exploits, but with curiosity or a need to "collect badges" of access.

I've seen people grant themselves rights they shouldn’t have by jumping into groups like:

  • SQL-DBA-Privileged
  • L3Support-AllRegions
  • L4-DomainControllerRoot

…simply because the group name sounds like it might give them “helpful” access. Unfortunately, these names often reflect elevated permissions, and even if the user doesn’t intend harm, they may suddenly gain admin rights across systems.

🧸 A Little Fun with Honeypots

To surface this behavior, I sometimes set up honeypot groups — fake groups with names that sound privileged but don’t do anything at all. Just labels. I give them enticing names like ADM-SuperAdmins or GPO-DomainControllerRoot, and sure enough, people help themselves. It’s like watching Winnie the Pooh spot a jar of honey — they can’t help but dip in.

These honeypot groups are a useful way to highlight risky behavior, reinforce access discipline, and even trigger alerts for further investigation (when it works)

Why This Exercise Matters

This project came from a compliance requirement: Who can gain elevated access just by being added to a group?

I focused on two specific angles:

  1. Group Policy Objects (GPOs) assigned to groups other than Authenticated Users
  2. Application/system access groups with names that apply elevated access.

Section 1: GPOs Assigned to Groups (Other Than Authenticated Users)

If a group is assigned to a GPO, then simply being added to that group can grant you all kinds of policy-based privileges — mapped drives, software, RDP rights, shutdown permissions, etc. Yet this is often overlooked.

Here’s a script that:

  • Retrieves all GPOs
  • Filters out Authenticated Users and system groups
  • Shows the group assignments for auditing
  • Outputs to screen and log file

Script: Get-GPOAssignments.ps1

You may need to amend the trustees as the default permissions need to be removed, more on that after the script:

Import-Module GroupPolicy

$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
$logFile = Join-Path $scriptPath "GPO_Assignment_Report_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"

function Get-DomainName {
    param([string]$trustee)
    if ($trustee -match '\\') { return $trustee }
    try {
        $ntAccount = New-Object System.Security.Principal.NTAccount($trustee)
        $sid = $ntAccount.Translate([System.Security.Principal.SecurityIdentifier])
        return $sid.Translate([System.Security.Principal.NTAccount]).Value
    } catch {
        return $trustee
    }
}

$excludedTrustees = @(
    "BEAR\Domain Computers",
    "BEAR\Domain Admins",
    "BEAR\Enterprise Admins",
    "NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS",
    "NT AUTHORITY\SYSTEM"
) | ForEach-Object { $_.ToUpper() }

$gpos = Get-GPO -All
$report = @()

foreach ($gpo in $gpos) {
    $acl = Get-GPPermission -Guid $gpo.Id -All
    $filtered = $acl | Where-Object { $_.Trustee.Name -ne "Authenticated Users" }

    $validEntries = @()
    foreach ($entry in $filtered) {
        $fullName = Get-DomainName $entry.Trustee.Name
        if ($excludedTrustees -contains $fullName.ToUpper()) { continue }
        if ([string]::IsNullOrWhiteSpace($entry.Permission)) { continue }
        $validEntries += [PSCustomObject]@{
            Trustee    = $fullName
            Permission = $entry.Permission
        }
    }

    if ($validEntries.Count -gt 0) {
        $report += "GPO: $($gpo.DisplayName)"
        $report += "----------------------------------------"
        Write-Host "`nGPO: $($gpo.DisplayName)" -ForegroundColor Cyan
        Write-Host "----------------------------------------" -ForegroundColor Cyan
        foreach ($item in $validEntries) {
            $line = "Trustee: $($item.Trustee) | Permission: $($item.Permission)"
            $report += $line
            Write-Host $line
        }
        $report += ""
    }
}

if ($report.Count -eq 0) {
    $msg = "No GPOs found with assignments other than 'Authenticated Users' and excluded groups."
    $report = $msg
    Write-Host $msg -ForegroundColor Yellow
}

The report will then give you the name of the GPO and the entry to need to look for is "GPOApply" this will mean the GPO is applied to that group.

GPO: STW IS Default User Policy
----------------------------------------

Trustee: STWATER\IS-Administration Function | Permission: GpoApply
Trustee: STWATER\GPO-Override Windows Colours Policy | Permission: GpoApply
Section 2Application Access Groups in a Sensitive OU

Next, I looked specifically in certain OU sections of the domain. This is where elevated access groups often live — the kind that control rights to apps, services, and infrastructure.

The goal here is to identify naming conventions that give people far too much access to platforms/systems that does not comply with least privileged access so "ease of support" 

Script: Find-HighAccessGroups.ps1

Import-Module ActiveDirectory

$scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
$logFile = Join-Path $scriptPath "ADMFullAccess_Groups_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
$searchBase = "OU=Groups,DC=Bear,DC=local"

$groups = Get-ADGroup -Filter {
    Name -like '*Administrative-*' -and Name -like '*GlobalAccess*'
} -SearchBase $searchBase -Properties Description

if (!$groups) {
    Write-Host "No groups found matching criteria in $searchBase" -ForegroundColor Yellow
    exit 0
}

$report = @()
foreach ($group in $groups) {
    $line = "Group Name: $($group.Name) | Description: $($group.Description)"
    $report += $line
    Write-Host $line
}

$report | Out-File -FilePath $logFile -Encoding UTF8
Write-Host "`nReport saved to: $logFile" -ForegroundColor Green

Conclusions

If you don’t know what your groups are doing — and who can get into them — then you don’t know who has access to what. These kinds of scripts make access visible, which is the first step toward making it secure.

And if someone falls for the honeypot groups? Well then the honeypot did exactly what it was designed to do. It’s not a trap if you’re not sneaking around looking for the honey.

Previous Post Next Post

نموذج الاتصال