Getting started with Lithnet Password Protection - Part 1 - Blocking compromised passwords with the 'Have I Been Pwned?' password list

NOTE: Please visit for the most up-to-date setup instructions

 In this guide, we will look at how to set up Lithnet Password Protection for Active Directory (LPP) from scratch. We'll configure a basic password policy, and integrate the pwned password data set to prevent users from changing their password to one that is known to be compromised.

This guide will focus on testing in an Active Directory domain, by installing the agent on a domain controller. However, for testing purposes, you can install the agent on a member server or workstation. The only difference is you'll need to test using local accounts, rather than domain accounts.


  1. You'll need to be using an x64 version of windows. LPP is a x64-only application.
  2. You must have local administrator rights on the server you want to install the agent on. For domain controllers, this means being a member of the Domain Admins group.
  3. Download the latest version of the NTLM passwords from the pwned password list (scroll to the end). Make sure you get the "NTLM Ordered by hash" version. Use the torrent link if you are able to so, as this helps minimize bandwidth and costs. Uncompress the file, and place it on your server to import later in the process.
  4. Download the latest version of LPP from the github site.
  5. Create a user for testing. Once again, if you are installing this on a domain controller, it will need to be a domain user, otherwise it must be a local user.

Selecting your store strategy

The LPP 'store' is essential a flat-file database of password hashes, efficiently stored in a binary format to maximize speed, while conserving space. Each domain controller must have read access to the store in order to compare incoming password changes against the compromised password lists. There are several different ways you can achieve this. Each has its own pros and cons, and you'll need to decide what's best for your environment.

Option 1: Each server accesses a single copy of the store via a file share

In this configuration, each server with LPP installed points to a network share that contains the single copy of the store. The benefits are that there is only one copy of the store to be managed, but the downside is that if the file server goes down, the password filter will be unable to perform compromised password checking. This might also be an issue for distributed environments, where bandwidth and latency between domain controllers and the file server is an issue. Remember, the agent must be installed on every writable domain controller in your environment, so they will all need read access to this store. If this is your preferred strategy, create your share, and grant the server's computer accounts read access to the store before you proceed. Users who be managing the store will need read and write access to this folder.

Option 2: Each server has its own copy of the store

In this configuration, each server with LPP installed has a local copy of the store. This means the store will always be available, and there will be no bandwidth or latency issues. The downside is that if you want to update the store with new passwords, you need to update it on each server manually. Updates to the store will be infrequent, so this may not be an issue. As the store is flat-file based, it is easy to copy around with a tool like robocopy and xcopy.

Option 3: Each server has its own copy of the store, but it is replicated with DFS-R

This is the configuration we recommend. Each server with LPP installed has its own copy of the store, but DFS-R is used to replicate and keep changes in sync. This means that new passwords can be added to a single server, and DFS-R will replicate those changes to the other servers. Do NOT place the store in the SYSVOL folder. Create a dedicated replication group for the LPP store.

Part 1: Install the software

1. Once you've completed the prerequisites, and decided on your store strategy, you can begin the installation process. On your chosen server, install the LPP agent, ensuring that you select all features for installation.

2. Select a path to hold the store of compromised passwords and banned words. If you are using the 'file server' store strategy outlined above, this will be the UNC path to your share. Otherwise, pick a local path and ensure that the drive that hosts the store has enough space on it. You will need at least 6GB of space to hold the HIBP pwned password list.

3. You'll need to reboot the server for the password filter to come online. Note that the password filter will remain inactive even after a reboot until we configure the group policy to enable it.

4. If you have more than one domain controller, repeat the process on the other domain controllers.

Part 2: Build the store

Once you've downloaded the NTLM ordered by hash version of the pwned password list, you can start to populate the store. If you're not sure if you downloaded the ordered by hash version, this is the time to double check. While the 'NTLM ordered by prevalence' version will work, it is extremely slow to process. The SHA1 hash lists will not work at all.

If you can, add the store path as an exclusion to your anti-virus software, at least for the process of building the store. It will make the process significantly faster.

Open a PowerShell window and run the following commands, replacing the store path, and path to the pwned password text file as appropriate.

This will read the text file and convert the hashes into a much smaller binary format. So while the plain-text hash list is about 20GB in size, the final store size should be about 6GB.

This process usually takes about 40 minutes, so grab yourself a coffee, and perhaps have read of the PowerShell command reference to familiarize yourself with the other cmdlets available.

Once the import is complete, you can delete the HIBP text file if you need to save space.

There is another cmdlet, Import-CompromisedPasswords, that you can use to import any plain-text password lists you may want to add to your compromised password store.

If you are using the standalone file store strategy, you should now copy the store folder to your other domain controllers. If you are replicating with DFS-R, create your replication group and wait for the replicas to sync up before proceeding.

Part 3: Configure the Group Policy

We can now configure the group policy to enable the agent and check passwords against the store. Open the Group Policy Management MMC, create a new GPO, and link it to an OU that your server is in. There is no harm at linking this at a higher level in the OU hierarchy if you prefer, as the policy only takes effect on machines that have LPP installed.

Note: If you have a specific machine where you perform group policy maintenance from, you'll need to install LPP on there, but select only the "Group Policy Templates (ADMX)" option in the installer. This will only copy the ADMX files to that server to allow you to edit the LPP policy settings. The group policy guide on the wiki has information about setting up a central policy store as an alternative to this.

Give the policy an appropriate name when prompted, then right-click the policy, and select Edit. If you are not ready to make the policy live at this stage, right-click the policy, and untick Link Enabled.

Navigate to Computer Configuration\Administrative Templates\Lithnet\Password Protection for Active Directory\Default Policy

Here you can set the policies you want to enforce. Double click Reject passwords found in the compromised password store, enable the policy, and check both boxes to enable password set and password change operations.

Run gpupdate on the server with LPP installed, to ensure it gets these settings.

Part 4: Test the policy

The policy is now active, so we can take our test user, and attempt to reset their password to one that we know is in the compromised password store. Let's use P@ssw0rd, because I know that it is in there.

And we should see that the password change was rejected.

Unfortunately, the Windows error messages do not tell the user anything other than the standard 'you can't use that password'. You'll need to find a way to communicate to your users that you are checking against known compromised passwords, and if their password change is rejected, it could be because they are using a password that has been compromised.

We can use Event Viewer to validate that it was LPP that rejected the request. For every attempt, there will be two event entries. The first will be an event to say that a password change or set request was received by the filter.

If you don't see this event entry, there are a couple of possible explanations;
  • You haven't rebooted the server since installing LPP
  • The password change was processed by another domain controller. In an Active Directory environment, any writable domain controller can process a password change, and only the one that initially receives the request validate that it meets the requirements. This is why LPP must be installed on all writable domain controllers. 
After that entry, there will be a warning event giving the reason the password was rejected. If you want to build automated reporting based off these events, there is a full list of event IDs and descriptions available.

You can also test password quality without changing them in Active Directory by using the PowerShell module's Get-PasswordFilterResult cmdlet.

The cmdlet will return a code that indicates if the password change was approved. Note that this cmdlet only tests the password against the LPP filter. A real password change may still be rejected by other password filters, or Active Directory's out-of-box password policies.

If you just want to test if a compromised password exists in the store, use the Test-IsCompromisedPassword cmdlet. Get-PasswordFilterResult will process the password change according to all group policy settings, whereas Test-IsCompromisedPassword justs checks to see if that password is in the store.

Part 5: Audit existing users

Now that we have stopped users from changing their password to one that has been compromised, what do we do about all the existings users who may already be using compromised passwords? Using the Test-IsADUserPasswordCompromised PowerShell cmdlet, you can compare users current password hashes against the compromised password store. Read the full guide on the wiki for the prequisites and example scripts you can use to audit these users.

Next Steps

Part 2 of this guide will show you how you can block common and context-based words from being used in passwords.