Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.


Module of the Month: Have I Been Pwned?

Breached passwords not only pose a threat to personal information but can give attackers the keys to your site. But how do you know if a password has been breached? SilverStripe Developer and security buff Simon Erkelens has answers in November’s Module of the Month, Have I Been Pwned?

Read post

Security is a big deal. Almost daily, new data breaches are exposed, passwords and usernames stolen, and phishing attempts are now such a regular occurrence that we can’t even keep up with the latest trends.

There’s an obvious risk in the reuse of passwords. So, if your password turns up in a breach like the Yahoo breach, you should consider that password unsafe to use. But when is a password unsafe to use? It’s almost impossible for one person to keep up with all past and present data breaches. Or is it?

Who is Troy Hunt?

Allow me to introduce Troy Hunt, a security researcher from Australia and the brains behind HaveIBeenPwned which he built to help detect if a password has been exposed in a breach.

Almost all known data breaches that exposed passwords are loaded into the website and made available for checking accounts, either through the website or an API. You could check your own account or those belonging to users of your website.

Some stats from HaveIBeenPwned

If you’re wondering what ‘pwned’ means, the term originated from gaming and describes being defeated or bested by an opponent. At the time of writing this, HaveIBeenPwned highlights:

  • 316 pwned websites
  • 5.5 billion pwned accounts
  • 500 million pwned passwords

That’s an average ratio of 10.7 accounts per password!

As passwords are still the primary authentication method on the web, it’s important that they’re not only strong, but unique. Of course, Multi-Factor Authentication is a thing and you should seriously consider implementing it but there’s no excuse for a weak, duplicate password.

If you run a website, it’s a good idea to make sure that anyone accessing your CMS isn’t reusing their password. If the breach were to occur on another website where the same password was being used, this could expose your site.  

Here’s how HaveIBeenPwned works

First off, sending your password to “some online service” is not always a good idea but I make an exception for HaveIBeenPwned. The site is very secure and does not store your submitted password.

When checking passwords against the HaveIBeenPwned API database, they’re never sent in plain text but instead hashed with the SHA1 hashing algorithm rendering them unrecognisable. For example, this means the password ‘Passw0rd’ becomes:


Then, only the first five characters of the hash are sent to HaveIBeenPwned. In this case:


To this request, HaveIBeenPwned responds with all results that include this starting hash, but without the starting five characters. That way, no actual password is sent or received and the check to see if the password is unique can be done locally.

In this case, we’d get a list of all known passwords starting with the first five characters above. We can then compare the rest of the hashed password with what’s returned and see if the password is in the list.

The list in question contains at least 381 results, so even in the unlikely event that it’s intercepted, a malicious interceptor must first manage to unhash the SHA1 algorithm and then test all 381 results.

For a more detailed explanation of how the communication between HaveIBeenPwned and your server works, check out their privacy statement.

The HaveIBeenPwnd module

The HaveIBeenPwnd module flags if a CMS user’s password is in the Pwned Password database.

composer require firesphere/silverstripe-haveibeenpwnd

When a password is found

The module aims to create a user friendly experience without compromising security, so sends a notification rather than simply blocking the password. When installed, the module identifies if a user’s password has been marked as pwned and the user gets a message in a separate CMS tab explaining that the password is no longer safe to use.

The known breaches list

This is to inform the user about the breaches in which their email address has been found so they can take appropriate action if needed.

Aggressive expiration

When a user logs in with a known breached password, the module will expire the password and force the user to reset their password via the ‘forgot password’ functionality. Although intrusive, it’s a much needed feature otherwise the login will remain vulnerable.

The usage of the ‘forgot password’ option versus ‘change password’ is intentional because if the password is breached, we should consider the account breached. With this in mind, going to ‘change password’ where the user must first enter their original password only exposes the account to more risk. Forcing a reset will ensure the reset email goes to the original user, not a perpetrator.


There may be situations where it’s necessary to allow exceptions for short periods of time. Because of this, the module offers the option to disable the lockout entirely, on a member-level, or to allow breached passwords site wide programmatically. Pwned counts still work and are visible in the user profile but they’re no longer blocked. While this may not be best practice, it’s an addition that could ease the transition to the new system.  


The module is very straight forward from the beginning. If default settings are used, it will register the default PasswordValidator from SilverStripe for you and hook into that validator to check against HaveIBeenPwned.

If you’re using your own custom validator, you’ll need to have the same extension points as the normal validator (updateValidatePassword) and register the extension against that validator in your YML file:

- Firesphere\HaveIBeenPwned\Extensions\PasswordValidatorExtension

That’s all you should have to do to get it working with your own validator.

To allow breached passwords, you can set the flag in your YML as well:

Name: MyPwnConfig
after: HaveIBeenPwnedConfig
allow_pwnd: true
save_pwnd: true

The save_pwnd flag is to save the sites on which the user’s email address or username has been found for the known breaches list explained above.

What next?

For a start, I strongly suggest you check your email address and passwords in HaveIBeenPwned. It’s a secure service but if you’re still unsure, you can download the Pwned Passwords list and do the check yourself. If the results indicate you’ve been pwned, consider following the recommended steps.

Next, you can help protect your website and CMS users by installing the HaveIBeenPwnd module and encouraging the use of unique passwords.

If you have any questions, feel free to hit me up on the SilverStripe community Slack channel (@firesphere).

And as per usual, give it a try, contribute, and enjoy!

Want to get involved in the SilverStripe community?

Get acquainted with the SilverStripe developer community on Slack.

Join the SilverStripe Slack community channel

About the author
Simon Erkelens

Simon is a developer at SilverStripe. When not at work, he's writing other programs or focusses on one of his modules he wrote or co-wrote. Or writing new things.

As a real backend developer, he's usually staring at a dark screen with code only. Although every now and then, he can be convinced to work on some frontend things or testing.

In real life, he looks nothing like the cow in his avatar, but he does love cows (both alive and medium rare)

Post your comment


No one has commented on this page yet.

RSS feed for comments on this page | RSS feed for all comments