User registers account on a web app. Passwords are salted and hashed. But is it safe to check the password against the HIBP Pwned Passwords API, before salting and hashing it? Of course the app uses TLS.

So if the password is found on any breach - don't allow to register an account. If password not found in breach - salt it and store it in a database.

Same would apply if changing the password.

  • 1
    What do you mean by "is it safe to check the password against HIBP API"? If the check is sufficient? – Tom K. Mar 12 '18 at 15:30
  • 8
    What value does this add for your users? Will registrants even have half a clue as to what pwned passwords are when you warn them of the futility of abc123? Even "safe" and KeePass'd passwords might have been pwned. Why not provide a password strength meter? – MonkeyZeus Mar 12 '18 at 16:53
  • 10
    @MonkeyZeus because "Password123!" does pretty well on password strength meters (12 characters from four character classes), but is a crap password. It also doesn't meet NIST or NCSC guidelines, whereas checking HIBP would (at least, would be part of). – Martin Bonner supports Monica Mar 12 '18 at 20:48
  • 3
    @MartinBonner If a user is determined to be unsafe then they will be unsafe. If you try forcing them into safety then you better be providing a darn good service because they will stop using your service if it's too cumbersome. Password123$! is a presumably a strong but crap password as well but it has not been pwned. I am not saying that the HIBP is useless but OP's planned implementation will lead to frustration, forgotten passwords, sticky-note passwords, and flat out finding a different provider of the same service. – MonkeyZeus Mar 13 '18 at 12:59
  • 1
    @MonkeyZeus The API returns the number of times a given password has been pwned, so you could set your system to only show a warning if the password had more than a given number of breaches. So you would be able to allow them to use a "safe" password that just happened to have been pwned once, while still using the API to block heavily pwned ones like "Password123!". – Spudley Mar 13 '18 at 21:35

Have I Been Pwned? allows anyone to download the full database to perform the checks locally.

If that's not an option, using the API is safe, since it uses k-anonimity which allows you to perform the check without transmitting the full password / hash.

  • 12
    By no means does k-anonimity make something safe, especially when their k is somewhere in the hundreds. Few web pages prevent attackers from making a few hundred login attempts against an account. – Tgr Mar 13 '18 at 6:17
  • 3
    The API doesn't use k-anonymity as it traditionally understood (which would be hard anyways since the set of all possible passwords is basically infinite). You request a hash prefix of length n and get 1/16^n of the whole database. So for the recommended n=5 and assuming one is fine with SHA-1 collisions, k would be ~ 1.4*10^42. – phihag Mar 13 '18 at 7:10
  • 1
    @phihag With the recommended n=5 hex digits, that ends up leaking 20 bits of information on the password to HIBP (or whoever intercepts communication or compromises HIBP). That's a non-trivial information disclosure, especially considering the general quality of passwords. – marcelm Mar 13 '18 at 12:50
  • 2
    Definitely go for the k-anonymity "search by range" option (haveibeenpwned.com/API/v2#SearchingPwnedPasswordsByRange). As for leaking information - does it really leak that much? You leak 20 bits of the hash but both "password" and "correct horse battery staple penguin jalopy car park" might have the same first five characters of the hash. If the user has a poor password then you'll find a match and tell them. If they don't have a poor password then you've still got LOTS of hashing to do to get five-char collisions. – IBBoard Mar 13 '18 at 19:52
  • 1
    Um, no, k is number of hashes for which the service knows or can reasonably find out the corresponding password. If you take the claim of the service operator at face value, k ~= 400. But assume they know 100K more common passwords, which they kept secret, so the real k ~= 500. You check with the service until the user provides a password which passes, you create the account, the attackers associate the account with the call to the service based on timing, now they only have to try the account with the 100 passwords belonging to that hash prefix which they lied about. – Tgr Mar 13 '18 at 20:28

If the operator of the Pwned Passwords API is malicious (or the service is hacked by a malicious person, or someone intercepts your communication) it can lie about certain passwords (only return a subset of passwords it knows for that hash), record where the request came from, identify the website belonging to that ID, identify the account (based on creation time, for example) and test it with the passwords it lied about, for a decent chance of account compromise.

This is a fairly unlikely scenario (the owner of the API is a respectable security professional, the list of known hashes is public, and doing this kind of attack without being detected would be hard), so it depends on how risk-averse you are. If you run a discussion board, using the API is definitely a good idea. If you run an e-bank, maybe not so much.

Downloading the database and doing the checks locally is of course safer, but not a trivial task, given the size.

  • 6
    What, you think banks should be more secure than forums? That's not how the world currently works... – NH. Mar 13 '18 at 19:47
  • I agree with this answer much more than the top voted one, but I felt I had to downvote because you didn't just come down hard on sending passwords around to 3rd party services. – jpmc26 Mar 13 '18 at 21:55
  • 3
    @jpmc26 security is always about tradeoffs. Someone running their web blog or discussion board with neither the time or expertise to implement server-side checking for known passwords will be far better off using the API. Troy Hunt going evil / getting hacked is a very small risk. Half your users reusing their passwords and not changing them after some of the sites hosting their other accounts have been hacked is almost a certainty. – Tgr Mar 14 '18 at 2:56
  • 2
    @Tgr Exposing someone's bank password because they happened to use it on your blog and your blog sent the password to some third party service is never acceptable. – jpmc26 Mar 14 '18 at 3:04
  • 2
    If you reuse your bank password on random weblogs, it's only a matter of time until it gets cracked, whether or not those sites share it. Also if it is a strong password (although who would pick a strong password and then reuse it between a critical service and a random website), the attacker is in no way helped by learning the few first characters of the hash. On the other hand, you are certainly right that it violates user expectations... – Tgr Mar 14 '18 at 3:13

As asked, No.

As of the posting of this answer, the question asks if it is safe to send a password "before salting and hashing it", which means in plaintext. You should never send a password in plaintext to a third party (second party may be OK if you are currently logging in). Even hashing the password is not enough, as a Rainbow Table can be used to look up the password. This is why when I saw someone (hashing and) sending every single password in a KeePass database to HIBP, I immediately called them out on it.

As other answers have pointed out, there is a new version of HIBP that includes k-anonymity (see that link and the other answers for more info). However, this is still divulging some information about the passwords (to HIBP, and any potential MITM attacker. Divulging some information is nowhere near as bad as leaking the entire password, but is still something you should be concerned about. What you really want is your passwords to be secure, not anonymous.

Ultimately, if you want to ensure that no information about your passwords is leaked in the checking process, you have to download the entire DataBase of pwned passwords, and hash and check your password locally (in this case, on the server because noone wants to download the entire DB just to create an account). Just don't store the password or the hash you are comparing to the DB anywhere, only store the salted hash in your actual password database.

  • 4
    Thank you. "Never send passwords to anyone" is the only sane approach. The other answers hemming and hawing over that question is terrifying. – jpmc26 Mar 13 '18 at 21:50

Just to add something to the previous answers I can't think of any other serious security issues of checking passwords against the site, but from a user experience perspective it might be better to check the email and password together and then notify the user if both return true. I also wouldn't prevent them from using it if it does return true. I've just tried out 30 freshly generated random passwords and and 4 of them returned true on the site. I'm not 100% sure how you'd implement it using the API but it'd probably be what I'd look into doing.

  • 1
    Problem with that: One of my passwords returns true x3, but the only email it was associated with returns false. This is a password that I guarantee you only I have used because of its length and complexity. Also, were those passwords <9 characters? There's your problem. Good passwords are usually at least 10 chars. Bottom line, if your password is there, you should consider not using that password. If it's in there more than 2 or 3 times, ditch that password. – Duncan X Simpson Mar 13 '18 at 0:41
  • 3
    Your password generation algorithm clearly doesn't create passwords with an entropy of more than about 32 bits. – CodesInChaos Mar 13 '18 at 16:33
  • 1
    “Random” on its own, doesn’t mean secure. The passwords must be unique, because if someone ever generates the same password, it may end up being leaked independently of you. If your random password generator produces passwords that not only fail to be unique, but are also already in a database of known passwords, ditch that whole password generator, because you know it will give out pwnable passwords. – mwfearnley Jan 18 '19 at 10:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.