Last updated on 27 May 2020
Group Policy preferences were introduced by Microsoft in Windows 2008 allowing administrators to configure unmanaged settings (settings which the user can change) from a centrally managed location – Group Policy Objects (GPO) [1].
Among the preference items configurable through Group Policy preferences are several that can contain credentials: Local Groups and User Accounts, Drive Mappings, Schedule Tasks, Services, and Data Sources.
These credentials are stored within the preference item in SYSVOL in the GPO containing that preference item. In order to obscure the password from casual users it is encrypted in the XML source code of the preference item [2]. However anyone who gains access to SYSVOL can decrypt the passwords because Microsoft published the Advanced Encryption Standard (AES) encryption key [1]:
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
Microsoft addressed this issue in MS14-025 [4] however this update only prevented the creation of new Group Policy Preference items containing credentials; it did not remove any existing instances as this was considered too disruptive. Therefore network administrators must take action to find and remove these vulnerable items.
This vulnerability has been designated CVE-2014-1812.
Several tools exist to exploit this vulnerability including:
Get-GPPPassword (PowerShell – http://obscuresecurity.blogspot.co.uk/2012/05/gpp-password-retrieval-with-powershell.html)
gpp (Metasploit Post Module – http://www.rapid7.com/db/modules/post/windows/gather/credentials/gpp)
gpprefdecrypt.py (Python – http://esec-pentest.sogeti.com/public/files/gpprefdecrypt.py)
gpp-decrypt-string.rb (Ruby – http://carnal0wnage.attackresearch.com/2012/10/group-policy-preferences-and-getting.html)
However each of these existing tools have a significant weakness. Get-GPPPassword must be run from a Windows machine, the gpp Metasploit post module requires a meterpreter session, gpprefdecrypt.py and gpp-decrypt-string.rb require you to manually extract the cpassword for decryption, and finally the version of gpprefdecrypt.py available for download no longer works at the time of writing (due to an update to PyCrypto that removed the default iv of 16 bytes of zeros).
I therefore wrote a new cross platform tool, dubbed GP3Finder (Group Policy Preference Password Finder), to automate the process of finding, extracting and decrypting passwords stored in Group Policy preference items. This tool is written in Python (2.7) and depends on PyCrypto and PyWin32 on Windows or subprocesses on *nix based operating systems.
GP3Finder has been released open source under the GPL2 license here a compiled executable for Windows is also available here.
Update v4.0
On a recent test I had compromised a single Windows host and had remote desktop access as a low privilege user. Since I couldn’t map the C$ share remotely, and didn’t want to search through the dozens of Group Policy Preference items using built in Windows utilities, I quickly added the functionality to gp3finder instead.
Note: Group Policy Preferences are cached locally under the (hidden) directory: “C:\ProgramData\Microsoft\Group Policy\History\” by default.
In this update I also add the option to specify the start path when searching a remote share. This allows you to quickly search for Group Policy Preference passwords when you have access to the C$ share without searching the entire drive.
Another significant change is that you can now specify multiple hosts to search – ideal if you have access to C$ on a number of hosts and want to check all of them. Note, this functionality is not threaded (yet) so can take some time to complete.
Finally I have changed some of the command line options to ensure they are as intuitive as possible (see below or –help).
Update v5.0
GP3Finder has been updated to Python3.
The PyCrypto dependency has been replaced by cryptography as the former no longer seems to be supported and has multiple known vulnerabilities (https://snyk.io/vuln/pip:pycrypto).
DefusedXML is now a dependency, it has been utilised to reduce the risk of parsing potentially malicious XML files.
A Dockerfile has been created to allow convenient execution. Additionally a repository on Docker Hub has been setup with an image that is automatically built from the master branch of the BitBucket git repository.
docker run grimhacker/gp3finder --help
A valid setup.py file has been created which installs “gp3finder” as a command.
Example Usage
Decrypt a given cpassword:
gp3finder.py -D CPASSWORD
The following commands output decrypted cpasswords (from Groups.xml etc) and list of xml files that contain the word ‘password’ (for manual review) to a file (‘gp3finder.out’ by default, this can be changed with -o FILE).
Find and decrypt cpasswords on domain controller automatically:
gp3finder.py -A -t DOMAIN_CONTROLLER -u DOMAIN\USER Password: PASSWORD
Maps DOMAIN_CONTROLLER’s sysvol share with given credentials.
Find and decrypt cpasswords on the local machine automatically:
gp3finder.py -A -l
Searches through “C:\ProgramData\Microsoft\Group Policy\History” (by default) this can be changed with -lr PATH
Find and decrypt cpasswords on a remote host:
gp3finder.py -A -t HOST -u DOMAIN\USER -s C$ -rr "ProgramData\Microsoft\Group Policy\History"
Find and decrypt cpasswords on hosts specified in a file (one per line):
gp3finder.py -A -f HOST_FILE -u DOMAIN\USER -s C$ -rr "ProgramData\Microsoft\Group Policy\History"
Note: the user this script is run as must have permission to map/mount shares if running against a remote host.
Additional options are available:
gp3finder.py --help
References
[1] [Online]. Available: http://www.microsoft.com/en-us/download/details.aspx?id=24449).
[2] [Online]. Available: http://blogs.technet.com/b/grouppolicy/archive/2009/04/22/passwords-in-group-policy-preferences-updated.aspx.
[3] [Online]. Available: http://msdn.microsoft.com/en-us/library/2c15cbf0-f086-4c74-8b70-1f2fa45dd4be.aspx.
[4] [Online]. Available: http://blogs.technet.com/b/srd/archive/2014/05/13/ms14-025-an-update-for-group-policy-preferences.aspx.
As always, if you have any comments or suggestions please feel free to get in touch.
Hi there,
If I use the -E switch to encrypt plaintext for “3rKb45rV”, I’ll get this:
E96x4zScqtIZc7dGnJAoDxYBa+RvGYh90cK1YoVm+Yw
If I put that into the Drive.xml file that GPP references and load up my user account, the drive will fail to map due to a network password error (0x80070056).
If I were to use a Windows Server 2008 DC to create the drive map, the cPassword attribute turns out to be:
LehuaWEr7GE2pOY47SZTTK5EA51GcCyOT9ct0h1d7hQ
If I then use your tool to decrypt that cpassword, it gives you the same plaintext string.
Basically, different encrypted cpasswords give you the same plaintext string, but only one of the cpassword works in drive.xml.
I know it is recommended to stop using cpassword with GPP, but our company still use it for reasons I won’t delve into. We do not have a 2008 DC anymore (the one I used earlier was just a test VM I spun up), therefore I’m using your tool to generate the cpassword.
Hi Ricky
I would first like to reiterate that using group policy preferences with passwords in them is a security vulnerability! Any attacker with a domain account can recover the credentials you are configuring.
I hope you can work to remove them from your environment in the near future!
However, thank you for letting me know about that error, I’ve tracked it down and it appears to be due to an incorrect conversion (utf-8 to utf-16 rather than to utf-16le). I have pushed a fix which resolves the problem for the example you gave, please let me know if you find it does not work.
Thanks for the fast response!
We are aware of the security issue. We’ve looked at the recommendations, however they do not really apply to us…
For example, we have a few clients are running servers in a Workgroup (for security or other specific reasons). These servers could be hosting databases, or file server stuff. Most of the time, these servers will have shares that will need to be mapped as drives in user sessions. Some users may have access to certain drives, some don’t.
To control this, we obviously need separate share credentials. The old GPP provides this sort of setup, but having that removed means we need to implement some sort of workaround (we haven’t found one yet).
I’ve downloaded the updated .py file and tried to convert it to .exe myself with py2exe. I’ve run the .exe but I’m getting a bunch of errors…..Would you be able to provide the the updated .exe as well?
Nevermind got it working.
Hi! Are you able to modify the program to put the results in quotation marks, because a password I am trying to decrypt has spaces after the password, but those spaces don’t show in cmd prompt, so if the results are in quotation marks, that would fix the issue. Thanks!
Hi Cooper
I considered wrapping the password in quotes, however quote marks are valid characters for a password so I thought that might cause confusion…
The spaces should be easy to see in the output file since there is a delimiter.
I have just pushed an update to try and make the output of -D clearer. It now includes the length of the password and that number of “-” on the line above and below. e.g.
$>python gp3finder.py -D /NzAelK9zD+fwK74rYBJ7rfyO/nX7Bwc0iyS7NLoJb+MTY1ib+XRyvRAPh5MS3vnuD4c3H9YSTXMEzcxzkzVtQ
Group Policy Preference Password Finder (GP3Finder) $Revision: 4.1 $
Copyright (C) 2015 Oliver Morton (Sec-1 Ltd)
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See GPLv2 License.
INFO: gp3finder: Decrypted password is 31 characters.
INFO: gp3finder: -------------------------------
INFO: gp3finder: My password ends in spaces!
INFO: gp3finder: -------------------------------
I hope that helps. 🙂