41

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.

Benoit Esnard
  • 13,942
  • 7
  • 65
  • 65
Bitenieks
  • 533
  • 1
  • 4
  • 5
  • 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
  • 11
    @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
  • 4
    @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
  • 1
    Don't use a simplistic password strength meter. Use something like [zxcvbn](https://github.com/dropbox/zxcvbn) – Nacht Mar 14 '18 at 00:55
  • @Spudley Yes, that is good advice but my comments have been in regard to OP's statement of "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." so there is no need to aim your conjecture at me; tell it to OP. – MonkeyZeus Mar 14 '18 at 12:11
  • 1
    Why not give your users the choice? There could be an option during registration that simply asks if the user would like to have their password checked by HIBP E.G a "Check password security through HIBP?" checkbox (This comment is for those concerned with not meeting users expectations) – GrumpyCrouton Mar 14 '18 at 17:08
  • @MartinBonner now it's been pwned. lol – John Jun 27 '18 at 20:34

3 Answers3

61

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.

Benoit Esnard
  • 13,942
  • 7
  • 65
  • 65
  • 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 06: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 07: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 (https://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
  • ...so k can be quite small for practical purposes. – Tgr Mar 13 '18 at 20:28
  • If you're really worried about leaking a small bit of your hash, then you could always mask it by sending it alongside a bunch of dummy requests with arbitrary faked hashes. The API response is quick enough that you could get away with doing that, and it would multiply an attackers problem space. But it's a very theoretical risk anyway; remember that the password has already had to travel unhashed from the user's machine to your server; that's a far more tempting target for an attacker than a small substring of the hashed password. – Spudley Mar 13 '18 at 21:43
  • 1
    "A small substring of the hashed password" means that the difficulty of a dictionary attack has been reduced one million times. (If you try to thwart the attacker by making a hundred fake requests alongside the real one then still ten thousand times.) – Tgr Mar 14 '18 at 02:53
  • @IBBoard _"As for leaking information - does it really leak that much?"_ - Yes. Leaking 20 bits means an attacker can do a pre-selection on what passwords to try, reducing the number of passwords the attacker has to try on-line by a factor of one million (2^20). For weak passwords, that is a very significant factor. – marcelm Mar 14 '18 at 12:52
  • @Tgr It would be quite hard for HIBP to be malicious. Given that the database is available to the public it is fairly easy to do regular audits, both through parallel query construction and checking that common passwords are in the database. If HIBP is keeping back a list of common passwords that they allow and later use to attack the service they would have to be excluding entire breaches, because you could easily check that all of a given breach is in the database. If a breach becomes public and HIBP don't add it, that would also quickly be detected. Is that your attack scenario? – jhoyla Mar 14 '18 at 15:12
  • @marcelm - But that's 20 bits of hash rather than password. The attacker can't directly reverse engineer password choices from that *except* for weak ones that have been rainbow tabled or previously leaked and cracked (which would be flagged to the user at registration). The attacker still needs to hash **every** other password to see what prefixes match, and if they don't have "correct horse battery staple penguin jalopy car park" and "correct horse battery staple penguin jalopy car park 2" they still need to hash both to check the prefix. – IBBoard Mar 14 '18 at 19:17
  • @Tgr and marcelm - To put this into perspective, what *is* the attack scenario that you're working with? HIBP only gets passwords, not usernames. If OP's server has been compromised then the attacker can collect username/password directly. If it was just OP's DB is dumped then the attacker has (hopefully salted) passwords and no HIBP requests. If the check is client-side and user is MitMed then you'd grab the password directly. If HIBP is malicious or a server-side check is MitMed then they don't know the user who just signed up (except some forums listing registration times). – IBBoard Mar 14 '18 at 19:26
  • @IBBoard yes, registration times on one hand. Also many hashes correlate to not just passwords but usernames (known from previous leaks). Worst case (from the attacker's POV) for an untargeted bruteforce attack where random common passwords are tried against random accounts, the search space is significantly reduced, as long as the site has a smallish set of users. E.g. 10K users, ~100 password guesses the attacker can associate with a hash, comes out to a pool of one million passwords vs. the original pool of 100 million. – Tgr Mar 15 '18 at 00:43
  • @jhoyla yes. And I agree it's hard to pull off and not a very realistic scenario, but not exactly impossible either. (Also the service could return different responses depending on e.g. IP - that kind of very targeted attack is hard to notice.) As I say in my answer, I wouldn't worry about it unless I were running a site with very high security requirements. But in any case, it's incorrect to claim that k-anonimity adds much to the security here. To the extent HIBP can be trusted, it can be trusted due to its transparency. – Tgr Mar 15 '18 at 00:49
14

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.

Tgr
  • 668
  • 3
  • 11
  • 8
    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 02:56
  • 3
    @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 03: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 03:13
14

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.

NH.
  • 1,004
  • 1
  • 9
  • 20
  • 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