Announcing Lithnet Password Protection for Active Directory

Hackers have never had it easier when it comes to performing credential-based attacks. Massive lists of breached user names and passwords are readily available on the internet for use in credential stuffing attacks against organizations. Even without the help of such lists, attackers can rely on the fact that people generally choose terrible, predictable passwords. Target a large enough organization, and you have a chance of finding a user with a password from a top 100 bad password list.

Keeping up with these sorts of threats is a challenge for every organization, no matter the technology they use. For a significant number of organizations, Microsoft's Active Directory is the core authentication service, connecting users and services across the enterprise. It is disappointing then, that AD hasn't done much to adapt to the changing threat landscape, with password protection capabilities that haven't changed in decades. A true sign of its age is that it stores passwords using an unsalted MD4 hash (a meaty target if ever there was one). Its out-of-the-box password policies leave a lot to be desired: even with password complexity enforcement turned on, AD is quite happy to allow a user to use objectively bad passwords like 'P@ssw0rd'. At the time of writing this post, that particular gem has been seen over 51,000 times in data breaches known to

In 2018, NIST put out new guidelines for password management. These offer practical recommendations that can help combat these sorts of attacks, with one that stood out as the most important to me.

When processing requests to establish and change memorized secrets, verifiers SHALL compare the prospective secrets against a list of known commonly-used, expected, and/or compromised values. For example, the list MAY include (but is not limited to):

  • Passwords obtained from previous breach corpuses
  • Dictionary words
  • Context specific words, such as the name of the service, the username, and derivates thereof
However, if you are using AD for authentication, you'll find that it falls short of being able to implement these and many other key recommendations.

Now, to be fair, Microsoft are not completely absent from the party here. Azure Active Directory provides infinitely better credential protection capabilities. There's been a significant investment made in the technology in AAD, and I have to say it offers some of the best account protection features in the market. Unfortunately, not everyone has AAD, nor is it (yet) a replacement for AD. AAD also comes at an additional cost, and the best of the account and password protection functionality is only included in its premium tiers.

I'm a firm believer that security essentials shouldn't be an additional offering that an organization must pay a premium for. We need to consider credential hygiene a security minimum, not an add-on. As a result, I decided to offer one way to close that gap, and make the technology to provide good credential hygiene freely available. I've spent the better part of a year working on that solution, and today, I'm releasing Lithnet Password Protection for Active Directory (LPP).

LPP is a module that you install on your Active Directory servers that uses a password filter to inspect passwords as users attempt to change them. Using group policy, you customize the types of checks you want to perform on those passwords and they are either rejected, or approved, and committed to the directory.

LPP gives you the ability to take control of what a good password means to you. Whether you want to adopt the NIST recommendations in part, or in full, it provides a rich set of group policy-based controls that allow you to enable any combination of the following checks on attempted password changes.
  • Block compromised passwords from being used. We've made it super easy to import the HIBP data set, but you can also import any plain-text passwords or NTLM hashes that you can get your hands on.
  • Block passwords based on certain words. Adding a banned word prevents it from being used as the base of a password. For example, adding the word 'password' to the banned word store, prevents not only the word itself, but common variants such as 'P@ssw0rd', 'pa55word!' and 'password123456!'. LPP is aware of common character substitutions and weak obfuscations and prevents their use through a normalization process
  • Define complexity policies based on length. For example, you can require number, symbol, upper and lower for passwords less than 13 characters, but have no special requirements for passwords 13 characters or longer. Reward length, with less complexity.
  • Regular expression-based policies. If regular expressions are your thing, you can define a regular expression that the password must match (or not match).
  • Points-based complexity. Assign points for the use of certain characters and categories and set a minimum point threshold a password must meet.
It also includes the ability to audit your users' existing passwords against the comrpomised password list. You'll be able to find the weak and known compromised passwords, and force those users to change their password.

While it's not the only service out there to offer custom complexity policies, or compromised password checking for AD, it has the following additional features;
  • Does not require internet access
  • No additional servers required for deployment
  • Passwords never leave the domain controller
  • Designed for large environments where high performance and reliability are required
  • Creates detailed event logs, easily digestable by Splunk or OMS
  • Uses a DFS-R friendly/compatible data store
I've put together a 3 part getting started guide to get you up and running with the most common scenarios quickly. You can also visit to the Lithnet GitHub site to view the documentation wiki, download the latest release, or inspect the code.

If you find any issues, or need some help, head on over to GitHub and log an issue.

You can follow me on Twitter or subscribe to the RSS feed to keep up to date with the latest news and updates.


None of this would be possible without Troy Hunt's service. Buy him a beer to say thanks! If you have not yet signed up to be notified when your account has been seen in a breach, do so now.

The capability to audit existing user passwords comes from the incredible work Michael Grafnetter has done with his DSInternals tools.

A special thanks to those who have dedicated time to help test the module and improve the documentation. Darren Robinson, Matt Solly, and Jaysn Rye in particular.