0

I am very new to authentication and cybersecurity in general, so I apologize if I have anything completely wrong.

My goal is to have the client side hash passwords before sending them to server side in order to protect users using the same password on multiple sites. For the sake of this question, assume server-side is secure (in my case, the hashed passwords from client-side are hashed again with Argon2 and then stored in the database). I understand that this provides no security benefit for users on my app and that other things such as SSL are much more important for keeping passwords secure in transit, but I'd still like to do this just in case.

I was planning on using SHA256 but heard that rainbow tables are a major security threat. Would using the username as the key in an HMAC hash mitigate that? Moreover, are there any better ways of protecting users who reuse passwords on multiple sites? Keep in mind that I can't use a salt because the resulting hash has to be consistent between logins when given the same username/password combo, and I can't use a secret key because it's client-side.

2

Hmm.

Your stated requirement is almost, but not quite, the same as the usual requirement of "If a hacker gets the db of users' password hashes, they should not be able to easily tell which users have the same password. This is usually solved by server-side salts.


You say:

Keep in mind that I can't use a salt because the resulting hash has to be consistent between logins when given the same username/password combo

I'll push back on whether that's actually true; salts are per-user, not per-login, so why not have the server look up the salt in the db and send it down to the client?


Ultimately, I'm not sure you're going to be able to solve this problem.

Let's say I (the hacker) find out that some user's password on memegenerator.com is letmein1234. Then I go to the the login page of your site and enter that password for them. As far as the server is concerned, that's literally identical to the real user trying to log in.

Remember also that the attacker gets to see the source code of the javascript, so any obfuscation that you do to the password client-side counts for zero security because it's completely known to the attacker.

If the user decides to reuse passwords across sites, I'm not sure there's anything you can do about it, unless you're willing to go all the way to implementing 2FA with Google Authenticator, SMS OTP codes, FIDO2 USB keys, etc.

  • 2
    If anyone does attempt the suggestion to use a per-user salt, keep in mind that this could be used for user enumeration attacks if implemented poorly. This hypothetical get-salt-for-user API endpoint should behave the same whether the user exists or not: Give bytes useful for salting a password, and give the same bytes every time for the same user identifier (whether that identifier existed before that first API request or not). – Ghedipunk Oct 4 at 18:19
  • @Ghedipunk Good point. – Mike Ounsworth Oct 4 at 18:21
  • @MikeOunsworth Thanks for the advice. I think you misunderstood my goal though. If I, the hacker, manage to intercept the network request sent by the client side, I shouldn't be able to figure out the original password. If the user's password is already leaked and they want to reuse it on my site, then a hacker will be able to enter, sure. But if a hacker manages to reverse the password in my DB or intercept the network request, he should only be able to use it on my site and not get the plaintext PW. – 101arrowz Oct 4 at 20:05
  • 1
    @101arrowz Hmm. I see where you're coming from, but I'm not sure that attack model is a realistic threat because, as you say in your question, intercepted network requests are a non-issue if you're using end-to-end TLS between the browser and your site's backend. About your second point: if the attacker is reversing the password hashes in your DB, it makes no difference whatsoever whether it was salted+hashed client side or server side. – Mike Ounsworth Oct 4 at 20:17
  • Back in the day, Microsoft used similar logic to your of "Let's send the hash over the network and not the plaintext password" in their NTLM protocol. In the end it was no better than sending the plaintext because of a class of attacks called Pass the Hash. – Mike Ounsworth Oct 4 at 20:19
1

The password that they type in is still their memorized secret, whether it gets passed over the network in a hashed form or not.

That is, you aren't keeping them from re-using a password at all; you're just shifting part of your authentication system over to the client side, where you have no control.

Rather than trying to find a way to mangle the password so that it isn't re-used, name and shame.

That is, use the Pwned Passwords API to detect when a user is using a previously leaked password, let them know that hackers are actively using that password, and use this as an opportunity to teach your users about password managers.

  • Thanks for the advice! I'm actually going to implement Pwned Passwords, but this idea is for the scenario that the hacker can see incoming network requests or manages to reverse an Argon2 password in my server-side DB. Should that happen I don't want them to have a plaintext password that can be reused on other sites - it should only work on my site. – 101arrowz Oct 4 at 20:09
  • @101arrowz, if an attacker has the power to arbitrarily reverse Argon2, well... let's just say their passwords would be the least of everyone's worries. – Ghedipunk Oct 4 at 20:12
  • 1
    Also, if you're using TLS properly, then all of the attacks are client side -- The attackers may be interested in your site, but it's the user who they're targeting, either by installing a malicious certificate in their CA store, downgrading their TLS to a vulnerable version, etc. If the attacker is doing that, they can do whatever they want to the Javascript code that's going to try to hash their password, as well. If that's the case, the user is well and pwned, and nothing you can do can protect them from their own system. – Ghedipunk Oct 4 at 20:17
0

I've come to the conclusion that hashing client-side is not particularly useful if I use TLS and have a secure database, both of which are true. This is because the only two things hashing on client side provide is protecting users if:

  1. Their network request is intercepted
  2. Their hash in the database is cracked

TLS prevents network requests from being intercepted and Argon2, which my DB uses, is next to impossible to crack as of today. Maybe in the future this could be useful if Argon2 can be cracked because then the password would only work on my site, but overall it's just about useless to do what I'm doing.

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.