12

I was wondering if passwords' inputs are "converted" locally on the client/web browser side or on the server side.

I'm pretty sure it's on the server side, but in that case it brings a concern to me: that means you are sending your password to a third party. Indeed the password will travel in a secure channel to the server, but in the end the server could do whatever it wants with it. Computing the hash yourself and sending it to the server would make the authentication process so much more secure.

In case of local scenario not possible could you explain like I'm 5 why this is not possible or a good idea?

8
  • 1
    There was a crypto se question on this: security.stackexchange.com/questions/8596/…
    – Nosrep
    Sep 9, 2021 at 1:24
  • 15
    The server is not a third party, it is the first party.
    – OrangeDog
    Sep 9, 2021 at 10:13
  • 11
    If you hash on the client side and send it to the server and store that hash verbatim, then an attacker, who stole hashes from the database, doesn't even need to crack them. He can just send them as-is to the server.
    – MechMK1
    Sep 9, 2021 at 11:36
  • 8
    Whatever you send to the server is the password. Hashing clientside is pointless. (Https on the other hand does serve a purpose for protecting the password) Sep 9, 2021 at 11:46
  • 7
    Why does it matter if the server can "do whatever it wants with it"? The server has all your data, it doesn't need your password.
    – Barmar
    Sep 9, 2021 at 18:39

6 Answers 6

32

I was wondering if passwords' inputs are "converted" locally on the client/web browser side or on the server side.

Usually (with regular forms-based logins) everything is done on the server side.

but in that case it brings a concern to me: that means you are sending your password to a third party. Indeed the password will travel in a secure channel to the server, but in the end the server could do whatever it wants with it

Yes it could. Hence the admonitions against password reuse.

Computing the hash yourself and sending it to the server would make the authentication process so much more secure.

On its own – no, it won't. It'll trade one risk for another.

With server-side hashing, if the server's database leaks (which happens a lot more often than TLS MITM), those hashes are mostly useless unless cracked one by one. With client-side hashing, the attacker could simply start sending those hashes like they were passwords! Instead of a one-time DB leak, now the attacker can log in to everyone's accounts, and they can keep those hashes to themselves and use them to log in months or years later.

(If you made both sides (first client, then server) hash the passwords, this still wouldn't stop a malicious server from storing the client-sent hashes and re-sending them somewhere else, again like passwords.)

To actually avoid both issues, you'd need more than just hashing; you'd need a slightly more complex protocol (e.g. some kind of challenge/response that isn't completely misdesigned like "HTTP Digest" was). You'd also want to ensure that the hash sent by the client cannot be reused at a later time (or even on a different site), as "replay attacks" are an issue with many protocols.

For example, the SCRAM protocol is now somewhat common among non-web systems such as PostgreSQL or MongoDB. However, to a web developer, all of those are significantly more complex than just making an HTML <form> – they require custom JavaScript code, and they often require multi-step interaction with the server.

It seems that "since we're adding JavaScript anyway", the web in general is moving towards protocols that don't involve passwords at all, such as WebAuthn which works with public-key signatures (a bit like SSH). This doesn't necessarily mean hardware dongles and 2FA – "Windows Hello PIN" is one example of WebAuthn provided by the OS.

8
  • 52
    Tl;dr: If you're sending a hash instead of a password, the hash is your password.
    – gronostaj
    Sep 9, 2021 at 14:24
  • 3
    @gronostaj that is so nicely formulated! It should be a quote on a t-shirt. :D
    – LPChip
    Sep 9, 2021 at 15:41
  • 1
    @gronostaj: If the client sends hashes, the server can still hash those, treating it exactly like a plain-text password. (Because it is.) If you actually hash (password + some site-specific fixed string), then bad practices like password-reuse are slightly mitigated, making it somewhat less than trivial to try the same password on other sites. (Unless I'm missing something?). Of course this is less good than challenge-response, but only requires one HTML form submission (with JS though to do the hashing). Sep 10, 2021 at 2:09
  • @PeterCordes: Slightly, but it's not really that different from a salt that most servers are already using. (Normally the salt is even unique to each user, helping against duplicate passwords in the same database.) To an attacker, if the client does H(password+string) and the server does H(hash), that's really not different from just doing H(H(password+string)). Sep 10, 2021 at 5:48
  • 1
    @user1686: Of course you'd still use salted hashes in the password file on the server, using a standard password-authentication library with the client-sent H(pass+string) as the "password". It doesn't help at all to protect this site, only helps to protect silly users who use the same password on other sites, by defending the original plain-text password from the attacker, unless they exploit the client itself to capture the password before H(pass+string) is done. (And then, the protection only benefits other sites. If another site leaks the plaintext password, they can use it here.) Sep 10, 2021 at 6:21
17

Computing the hash yourself and sending it to the server would make the authentication process so much more secure

No, accepting hashes instead of passwords would make the process much less secure. It would be the same as keeping plain-text passwords: if an attacker steals the server database containing usernames and hashes, they could instantly login as any user!

The whole purpose of hashing is to force attackers to reverse a one-way function: computing a hash from a know password is trivial, finding passwords matching a given hash is hard. Poor passwords like dictionary words are compromised when hashes are stolen, because computing hashes over 100'000 words is fast. Good passwords remain secure, because to compute the hash you need to guess the password first.

7

Yes, when you enter a password in a website, it is transmitted to the server in plain text, and the script on the server can then do anything with it, even store it in plain text as well. In order to protect users (websites are required by law in most countries), they hash the password and store the hash only, but that doesn't mean it always happens.

But even so, if a password hash is hacked, it could eventually be reversed to a plain password if really wanted and enough time is at hand (given they also get the security hash).

So what does this mean, always use unique passwords on every site. It is best to use a password manager that comes with a random password generator so you can just remember one password and forget about the rest. There are cloud based solutions but also local solutions depending on how much you distrust cloud computing.

As for the computing the hash locally, technically it is possible to do this with javascript but it brings a huge security risk. When you create a password hash, you use a unique hash (security hash) that the hash eventually is based upon. Because this unique hash is not known locally, it is not possible to decrypt the password. If you do local hashing, then suddenly the server must first send you the secret security hash to get the hashed password. A hacker could then easily decrypt any hash.

9
  • Some sites do use an additional secret (a "pepper") for password hashing but I don't think that's nearly as common as you're saying... Most only use a salt to make the hash unique, and salts are only useful because they're unique per-user, not because they're secret (they're almost always stored right next to the actual hash and get leaked together). Sep 8, 2021 at 14:34
  • @user1686 yes, I'm aware. OP asked for an answer that a 5 year old can understand. I did not want to make things overly complicated. :)
    – LPChip
    Sep 8, 2021 at 14:35
  • You can’t “decrypt” a hash. Hashing algorithms are not reversible. Sep 9, 2021 at 14:32
  • @AlexanderRevo I know. They have a hash and the salt, then use a dictionary attack to see what hash matches what password, so in essence they decrypt the hash to a password.
    – LPChip
    Sep 9, 2021 at 15:39
  • 3
    @LPChip not really. A dictionary attack won't help you crack the passwords that aren't in your dictionary - i.e. any password generated by any semi-decent password manager. In that scenario, having the hash for the password is only marginally more useful than having no hash: at most it might let you bypass the invalid password timeout on the server and avoid exhausting login attempts in case there is a limit -- which, I admit, could be an important advantage -- but you'd still have to brute-force the password by going through all the possible character combinations. Sep 9, 2021 at 16:04
2

TL;DR

You should hash the password both client side and then again server side. The password entered into the password entry box should exist only transiently in memory prior to hashing and should be deleted ASAP after that is complete.

Client Side Hashing

If a user re-uses a password, but it is hashed client side with a salt specific to that website, then if an attacker is able to read the traffic sent to the server they only gain access to the website that they have compromised the traffic to.

It is worth noting that if the attacker has the ability to write to the data sent to the client, then they can change the client so the password is just sent plaintext directly to the attacker. Client side hashing only protects against someone who has read access to the data going from client to server, but who doesn't have write access to the data going from the server to the client.

Server Side Hashing

When the server hashes the password prior to storing/checking it, the user is protected against an attacker who gains read access to the database. An attacker who can read the database will only see the hash of the password, but they will not know the preimage of that hash so they cannot authenticate with the server.

It is worth noting that if the attacker has write access to the database, can read memory of the authentication app, or can otherwise execute server side code then this protection doesn't help as the attacker could intercept the passwords before they are hashed on the server. However, only users who authenticate while the attacker has this access are at risk.

Do Both

A well designed app that cares about the security of its users should exercise a defense in depth strategy where you hash both on the client and the server so the user is protected from a variety of attacks. Server side hashing is more common than client side hashing, as read access to databases seems to be a more common compromise, but this doesn't mean you should ignore MITM attacks that gain read access to network traffic.

0
1

The password has to be hashed on the server side. If you hash the password on the client on the server side and send the hashed password to the server, then the hashed password is the thing the server checks to authenticate you, and "thing the server checks to authenticate you" is, by definition, the password. So by definition, the thing you send the server is the password. If the thing you send is generated by hashing something, then you're doing a bunch of extra work for no reason. More importantly, the replacing your password with the hash of your password server-side is useless, since it does nothing to change the threat vector of "if someone hacks into the server, they'll have data that will let them log into your account". The whole point is for the server to not have information that will allows authentication; authentication requires both your secret information (your password) and their secret information (what your password hashes to).

Indeed the password will travel in a secure channel to the server, but in the end the server could do whatever it wants with it.

Ummm... yeah? It's not like it's possible to create a security system that protects against the threat vector of "The people running the server are doing things they shouldn't be doing."

Computing the hash yourself and sending it to the server would make the authentication process so much more secure.

No, because, as I explained, that would mean that you're sending what is effectively your password. That is, you are sending something that, if intercepted, would allow free access to your account. Neither sending the hashed version nor sending the unhashed version addresses that threat vector. Either way, anyone who can read the traffic can impersonate you.

To address this vector, you'd need further security protocols, such as having the communication be over an encrypted channel, and requiring all messages to include a randomly generated salt that changes from session to session.

2
  • It is possible to create such security systems, by binding the credentials with the site's identity somehow (for example, U2F keys work by creating a unique keypair for each site, making it impossible for bad site A to "proxy" the verifier to site B, and similarly Kerberos works by issuing tickets that are unique to each service). In both examples, the server does not handle (neither store nor receive) data that'd allow a malicious server admin to access the same user's accounts on other servers. Sep 9, 2021 at 6:36
  • @user1686 You don't say what "such security systems" refers to, but it appears to be referring to "It's not like it's possible to create a security system that protects against the threat vector of "The people running the server are doing things they shouldn't be doing."" By that, I mean that it's impossible to create a system such that a site remains secure regardless of how badly the people in charge of the site run it. If there are credentials that are shared across sites, it certainly is possible for one site to remain secure even if a different site is poorly run. Sep 9, 2021 at 21:43
1

In case of local scenario not possible could you explain like I'm 5 why this is not possible or a good idea?

Never trust the client

With enough time and dedication, any client can be modified by the user.

Let's assume I'm a hacker.

  1. I just hacked the superuser.com database and now I have a very long list of usernames and their passwords.

  2. Except the passwords are hashed, so I can't actually use them.

  3. But the passwords aren't hashed on the server, they're hashed on my browser.

  4. So all I need to do is modify the JavaScript login script to remove the hashing process.

  5. And I already know all the hashes anyway.

As you can see, hashing the password on the client makes the whole hashing process itself useless.


By contrast, if the hashing was handled on the server instead, the whole story would change drastically:

  1. The passwords are hashed on the server, so I actually need to know the password.

  2. If I could bypass the hashing process on the server, I wouldn't even need to steal the passwords in the first place; I could just force the server to let me in.

  3. So now I need to spend a lot of time and power to find a password whose hash matches the hash I stole.

That's why hashing is always done on the server side, never on the client side. And that's also why we "Never trust the client".

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .