Site icon Windows Active Directory

How to detect abuse of GPO permissions

Detecting Abuse of GPO Permissions: What to Monitor, How to Investigate, How to Prevent

If an attacker can edit a GPO, they can often achieve silent, scalable code execution across fleets. This guide shows how to detect that abuse (and how to reduce your blast radius when it happens).

Why GPO-permission abuse is high impact

Group Policy is a centralized control plane. That’s the feature—and the risk. A single rights mistake (or an over-delegated group) can let someone:

  • Push startup/logon scripts, scheduled tasks, services, and registry changes across many hosts.
  • Grant themselves local admin everywhere via Group Policy Preferences or Restricted Groups.
  • Disable security tooling, weaken firewall rules, or turn off logging.
  • Target only high-value systems using security filtering or WMI filters.

If you want a refresher on how GPOs work end-to-end, start with Active Directory Group Policy and Managing GPOs with Group Policy Management Console (GPMC).

First-principles model: what a GPO really is

Detection becomes simpler when you model the “attack surface” correctly. A GPO is two things:

1) GPC (Group Policy Container) in Active Directory

Lives under CN=Policies,CN=System,DC=.... Stores metadata (version, extensions, security descriptor). Changing links and permissions is usually an AD object change.

2) GPT (Group Policy Template) in SYSVOL

Lives under \\<domain>\SYSVOL\<domain>\Policies\{GUID}. Stores files like gpt.ini, Registry.pol, scripts, and preferences XML.

Abuse happens when an attacker can modify either side:

  • AD-side: change the GPO ACL, change link targets (gPLink), create new GPOs, change WMI filters/security filtering.
  • SYSVOL-side: drop/modify scripts, scheduled tasks, preference items, or policy files.

Delegation is often necessary—but it must be intentional and narrow. See GPO Delegation and How to delegate permissions to create GPOs for the operational basics.

Common abuse paths (what attackers actually do)

1) “I can edit a GPO” → fleet-wide execution

  • Add a startup script under Machine\Scripts\Startup (runs as LocalSystem).
  • Create a scheduled task via GPP under Machine\Preferences\ScheduledTasks.
  • Modify Registry.pol to add persistence (Run keys, services, Winlogon settings).

2) “I can change GPO permissions” → future stealth + guaranteed access

  • Grant themselves Edit settings or Edit, delete, modify security on critical GPOs.
  • Add a nested group that looks legitimate (e.g., “IT-Workstations-Operators”) and delegate through it.
  • Change GPO owner to a service account to blur accountability.

3) “I can link GPOs (or modify gPLink)” → apply malicious policy without touching existing GPOs

  • Create a new GPO and link it to the Domain root, DC OU, or server OUs.
  • Change link order (higher precedence) or set the link as “Enforced”.
  • Use filtering to target only admin workstations or a specific server tier.

Filtering is a double-edged sword: it’s good for precision, and good for attackers too. Review GPO security filtering and WMI filtering with a detection mindset: “Who can change filters, and would we notice?”

Turn on the right auditing (without drowning)

Key idea: You don’t need “all logs everywhere.” You need authoritative change logs for:
  • AD object changes related to GPOs and GPO links
  • SYSVOL file writes under policy GUID folders

1) Audit AD-side changes: Directory Service Changes

Enable Advanced Audit Policy for Directory Service Changes on domain controllers (success at minimum). This is where you can catch:

  • GPO object modified (5136)
  • GPO object created (5137)
  • GPO object deleted (5141)

Then apply SACLs (auditing entries) on:

  • CN=Policies,CN=System,DC=... (to track GPO container changes)
  • High-value OUs (to track gPLink and gPOptions changes)

2) Audit SYSVOL writes: Object Access / File System

Turn on file system auditing where SYSVOL is stored on DCs and set auditing on policy folders for write events. This helps detect:

  • New or modified scripts (BAT/PS1/VBS) under GPO folders
  • GPP XML modifications (ScheduledTasks, Services, LocalUsersAndGroups, Registry, etc.)
  • gpt.ini changes and suspicious version bumps

Practical tip: focus auditing on critical policy GUID folders (Domain/Domain Controllers/Server tier) instead of blanket auditing every policy folder if volume is a concern.

High-signal detections and SIEM rule ideas

Detection A: Unauthorized GPO ACL changes

Trigger when a GPO’s security descriptor changes (AD event 5136 where the changed attribute is nTSecurityDescriptor) and the actor is not an approved admin group.

  • Where: DC Security log
  • Signal: 5136 + attribute: nTSecurityDescriptor on CN={GUID},CN=Policies,...
  • Enrich: map GUID → DisplayName via PowerShell

Detection B: New GPO created then linked quickly

Attackers often create a fresh GPO to avoid scrutiny, then link it to a high-value OU. Correlate: 5137 (new object under Policies) followed by 5136 on an OU’s gPLink.

  • Signal: “create → link” within 5–15 minutes
  • Higher severity: linked to DC OU / server tiers / admin workstations

Detection C: OU gPLink tampering

Detect changes to gPLink (link addition/removal) and gPOptions (block inheritance). Alert on unexpected precedence changes or enforced links.

  • Signal: 5136 on OU DN with attribute: gPLink or gPOptions
  • Enrich: decode GUIDs in gPLink, check link order changes

Detection D: SYSVOL policy-file writes

Watch for writes to suspicious paths: ...\Policies\{GUID}\Machine\Scripts\Startup, ...\Machine\Preferences\ScheduledTasks, ...\Machine\Preferences\Groups, Registry.pol, and gpt.ini.

  • Signal: 4663 (object access) on DC file system (if enabled)
  • Higher severity: script additions + GPO linked to many OUs
High-confidence “bad smell” combinations
  • Non-standard admin account changes GPO ACLs and modifies SYSVOL files within minutes.
  • New GPO created + linked to DC OU + contains startup script or scheduled task.
  • GPO permission change grants “Edit, delete, modify security” to a broad group (Helpdesk/IT-Staff/All-IT).
  • Filter changes (security/WMI) that narrow scope to “Admin” systems right before a policy update.

PowerShell checks: baseline, drift, and “who can edit what”

Your fastest detection wins come from answering two questions continuously:

  1. Who can modify critical GPOs? (permissions)
  2. What changed? (content drift)

1) List permissions on a critical GPO

# Requires RSAT: GroupPolicy module
Import-Module GroupPolicy

$gpoName = "Default Domain Controllers Policy"
Get-GPPermission -Name $gpoName -All |
  Select-Object Trustee, TrusteeType, Permission, Inherited |
  Sort-Object Trustee

2) Find “non-standard editors” across many GPOs

Import-Module GroupPolicy

# Customize this allow-list to match your org.
$allowed = @(
  "DOMAIN\\Domain Admins",
  "DOMAIN\\Enterprise Admins",
  "DOMAIN\\Group Policy Creator Owners"
)

Get-GPO -All | ForEach-Object {
  $gpo = $_
  $perms = Get-GPPermission -Guid $gpo.Id -All |
    Where-Object { $_.Permission -match "GpoEdit|GpoEditDeleteModifySecurity" }

  foreach ($p in $perms) {
    $t = ($p.Trustee.Name -as [string])
    if ($t -and ($allowed -notcontains $t)) {
      [pscustomobject]@{
        GPOName     = $gpo.DisplayName
        GPOGuid     = $gpo.Id
        Trustee     = $t
        Permission  = $p.Permission
        Inherited   = $p.Inherited
      }
    }
  }
} | Sort-Object GPOName, Trustee

3) Create a “known-good” snapshot you can diff later

Import-Module GroupPolicy

$out = "C:\\GPO-Audit\\"
New-Item -ItemType Directory -Force -Path $out | Out-Null

# Export permissions snapshot
$permSnap = Join-Path $out ("gpo-permissions-" + (Get-Date -Format "yyyyMMdd-HHmmss") + ".csv")

$rows = foreach ($gpo in Get-GPO -All) {
  foreach ($p in (Get-GPPermission -Guid $gpo.Id -All)) {
    [pscustomobject]@{
      GPOName    = $gpo.DisplayName
      GPOGuid    = $gpo.Id
      Trustee    = $p.Trustee.Name
      Type       = $p.TrusteeType
      Permission = $p.Permission
      Inherited  = $p.Inherited
    }
  }
}

$rows | Export-Csv -NoTypeInformation -Path $permSnap
$permSnap

Pair this snapshot with regular GPO backups (GPMC) to support clean diffing when something changes.

Investigation workflow: from event → GPO diff → scope of impact

Step 1: Identify the exact GPO and actor

  • From DC event logs, extract the DN (often includes CN={GUID},CN=Policies,CN=System,...).
  • Record: subject account, source workstation, timestamp, and changed attribute.

Step 2: Map GUID → DisplayName quickly

Import-Module GroupPolicy
$guid = "{PUT-GPO-GUID-HERE}"
(Get-GPO -Guid $guid).DisplayName

Step 3: Determine impact scope (where does it apply?)

  • Which OUs is it linked to?
  • Is the link enforced? Is inheritance blocked on target OUs?
  • Is security filtering or WMI filtering limiting it to a specific set (possibly “admins only”)?

Step 4: Diff the content (what actually changed?)

  • Use GPMC backup comparison if you maintain periodic backups.
  • Export a report now for evidence preservation:
Import-Module GroupPolicy
$gpoName = "PUT-GPO-NAME-HERE"
Get-GPOReport -Name $gpoName -ReportType Html -Path "C:\\GPO-Audit\\GPOReport.html"

Step 5: Confirm affected machines and timelines

  • Find machines in linked OUs and identify which have applied the policy recently.
  • On sample endpoints, use gpresult /h and review applied GPOs and last refresh time.
  • If you centralize endpoint logs, look for correlated changes: new local admins, new scheduled tasks, service installs, script executions.
Evidence preservation tip: If you suspect SYSVOL tampering, capture the GPO folder contents (policy GUID folder) and the AD-side attributes promptly. Attackers often “fix the permissions back” after deploying the payload.

Hardening patterns: prevent and contain

1) Reduce who can edit critical GPOs (and make it reviewable)

  • Use dedicated groups for GPO editing (per tier), not broad IT groups.
  • Eliminate direct user assignments; delegate to groups only.
  • Review nested memberships regularly (nested groups are how broad access hides).

2) Separate “create GPO” from “link GPO” from “edit GPO”

  • Creation rights: tightly controlled (avoid “everyone in IT can create GPOs”).
  • Linking rights: extremely sensitive on high-value OUs.
  • Editing rights: scoped to specific policy sets.

3) Require privileged access workstations (PAWs) for GPO management

  • GPO changes should originate from hardened admin endpoints only.
  • Alert when GPMC activity appears from a non-PAW subnet or non-admin workstation.

4) Version control for GPOs (treat them like code)

  • Frequent backups (daily for critical GPOs).
  • Documented change windows and approvers.
  • Automated diffing for drift detection.

5) Guardrails on SYSVOL

  • Monitor writes to policy folders; alert on scripts and scheduled task preferences.
  • Ensure only appropriate principals can modify GPO files.
  • Harden SMB and ensure DCs are patched (SYSVOL is a high-value target).

Operational checklist

Weekly

  • Review “non-standard editors” report across all GPOs.
  • Review recent changes to CN=Policies and critical OUs.
  • Spot-check security/WMI filters for unexpected narrowing.

Daily (for critical tiers)

  • Back up critical GPOs and retain snapshots.
  • Alert on 5136 nTSecurityDescriptor changes on critical GPO GUIDs.
  • Alert on SYSVOL writes to scripts, scheduled tasks, groups, and Registry.pol.

Bottom line: GPO permission abuse is best detected by correlating AD-side change events (who changed what) with SYSVOL writes (what payload was dropped) and link/filter manipulation (where it applied). Build a baseline of “who can edit which GPO,” alert on drift, and keep a fast diff workflow ready.

Exit mobile version