Grabbing Passwords from your Domain Controller (GPP MS14-025)

Another tool that is part of the Powersploit toolkit mentioned earlier is Get-GPPPassword.

One way to add a user (or change a password) for many users in a domain is through Group Policy Preferences (GPP).  This essentially adds a GPO to the domain with a username and an (encrypted) password for all the computers on the domain to grab and process.  The problem here is that Microsoft actually published the AES symmetric encryption key it uses right on MSDN.

GPOs are available for any authenticated domain user to read via \\domain-name-here\SYSVOL share.  In other words, any authenticated user (insider attack, spear phished creds, etc) can gain access to these credentials in cleartext.  The GPPs with the passwords are usually located in \\domain\SYSVOL\domain\Policies\{*}\Machine\Preferences\Groups\Groups.xml

In 2012, Chris Campbell wrote up a very easy to use Powershell script to search for these GPOs, decrypt the passwords, and print out the cleartext credentials.  The script has since been updated and uploaded to the Powersploit github repository.

In 2014, Microsoft finally issued the MS14-025 patch for this issue.  However they didn’t want to break anyone’s current processes by removing bad GPOs, so they simply disabled the Username and Password boxes and left it to the user to remove the bad GPOs.  Therefore, this attack vector will likely be very useful for a long time to come.


Setup  Your Testbed

Testing this vulnerability in a controlled environment is difficult.  It requires setting up a Windows domain and adding test users via GPP, which is beyond the scope of this blog.  Just trust me – if your environment contains passwords, you will see them.  The script will not do any harm – it is merely viewing the contents of GPO files, just like any other domain joined computer would.


How do I find a vulnerable host?

Check to see if your local system is joined to a domain.  This can by done by right clicking on My Computer and clicking properties.  If it lists a workgroup, then you are out of luck.  If it lists a domain, then you’re in business.

How do you attack that host?

This is the easy part.  Simply run Get-GPPPassword.ps1 from the command line, and everything else is done for you.


The script will automatically figure out your domain and go searching for GPOs with passwords.  This may take a while because it is likely going across the network and searching.

These tasks can actually be split up and improved upon.  First, copy all of the GPOs from the network location to a local location by copying the entire contents of \\domain\SYSVOL\domain\Policies (or if these files are very large in your domain, write a script to search for and only copy the relevant Groups.xml types of files). Now you can use a nifty script that Microsoft provides called Enum-SettingsWithCpassword.  This script alone provides very little information, but it is easy to edit the end part with all the Add-Member lines to provide additional information.  Here is what mine looks like:

Add-Member –membertype NoteProperty –name GPOName –value ($gpoName) –passthru |
Add-Member -MemberType NoteProperty -name Owner -value ($gpoOwner) -passthru |
Add-Member -MemberType NoteProperty -name UserName -value ($gpp.Name) -passthru |
Add-Member -MemberType NoteProperty -name Password -value (Get-DecryptedCpassword($gpp.Properties.cpassword)) -passthru |
Add-Member -MemberType NoteProperty -name Modified -value ($gpp.changed) -passthru |
Add-Member -MemberType NoteProperty -name ChangeOnLogon -value ($gpp.Properties.changeLogon) -passthru |
Add-Member -MemberType NoteProperty -name ChangeDisabled -value ($gpp.Properties.noChange) -passthru |
Add-Member -MemberType NoteProperty -name NeverExpires -value ($gpp.Properties.neverExpires) -passthru |
Add-Member -MemberType NoteProperty -name Disabled -value ($gpp.Properties.acctDisabled) -passthru |
Add-Member -MemberType NoteProperty -name GUID -value ($gpoGuid) -passthru |
Add-Member -MemberType NoteProperty -name Status -value ($gpoStatus) -passthru |
Add-Member -MemberType NoteProperty -name Path -value ($prefLocation) -passthru |
Add-Member -MemberType NoteProperty -name FilePath -value ($fileFullPath)

Notice that I also used the DecryptedCpassword utility (also provided on the same Microsoft page).  Once your script is ready, I prefer to dump the contents into a CSV file.  So the function would be run like this:

PS > Enum-SettingsWithCpassword("C:\Users\colesec\Desktop\GPOs") | Export-CSV C:\Users\colesec\Desktop\GPOsWithPass.csv

The other thing about this script is that it requires the GroupPolicy module for Powershell, which you probably don’t already have if you’re not running this from a Windows Server distribution.  No fear though – this is just an easy, free download from Microsoft.  Grab the Remote Server Administration Tools (RSAT), install, and you’re set.  More info here.

Good luck!

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>