72

There are very few websites that hash the users password before submitting it to the server. Javascript doesn't even have support for SHA or other algorithms.

But I can think of quite a few advantages, like protection against cross-site leaks or malicious admins, which SSL does not provide.

So why is this practise so uncommon among websites?

  • 11
    What advantages do you think there are to client side hashing of passwords? – Tim Lamballais Mar 18 '14 at 10:34
  • 7
    @TimLamballais A typical client can spend far more time on hashing than a server. So if you have a high performance implementation in the client (which rules out javascript in current browsers) you can use more expensive and thus stronger password hashes. It also means that the server never sees the password itself. Client side hashing is also a prerequisite for augmented PAKE protocols like SRP where impersonating the server doesn't give you access to the password. – CodesInChaos Mar 18 '14 at 10:58
  • 5
    Javascript isn't really that slow anymore. Modern javascript engines have become so fast that they are on-par with compiled languages and recent additions like typed arrays provide the proper tools for the number-crunching required for cryptography. – Philipp Mar 18 '14 at 11:57
  • 5
    @TimLamballais One advantage would be that the server never sees my real password, and cannot possibly leak it (yes, they can still leak the hash, but it should be salted by the domainname, so useless for login to other sites). But for the largest advantage see my comment to Phillip's answer. – Muis Mar 18 '14 at 13:43
  • 2
    A lot of people question whether any extra security is gained with this practice. One thing it does do is reduce risk. If you always hash or encrypt (I've seen steam/valve encrypt with a public key and I bet they are not decrypting) there is no chance of you ever having an embarrassing plaintext breech. No...it isn't any more secure but it isn't pointless – user11869 Mar 18 '14 at 14:34

11 Answers 11

38

Inventor of JavaScript password hashing here

Way back in 1998 I was building a Wiki, the first web site I'd built with a login system. There was no way I could afford hosting with SSL, but I was concerned about plaintext passwords going over the Internet. I'd read about CHAP (challenge hash authentication protocol) and realised I could implement it in JavaScript. I ended up publishing JavaScript MD5 as a standalone project and it has become the most popular open source I've developed. The wiki never got beyond alpha.

Compared to SSL it has a number of weaknesses:

  • Only protects against passive eavesdropping. An active MITM can tamper with the JavaScript and disable hashing.
  • Server-side hashes become password equivalents. At least in the common implementation; there are variations that avoid this.
  • Captured hashes can be brute forced. It is theoretically possible to avoid this using JavaScript RSA.

I've always stated these limitations up front. I used to periodically get flamed for them. But I maintain the original principle to this day: If you've not got SSL for whatever reason, this is better than plaintext passwords. In the early 2000s a number of large providers (most notably Yahoo!) used this for logins. They believed that SSL even just for logins would have too much overhead. I think they switched to SSL just for logins in 2006, and around 2011 when Firesheep was released, most providers switched to full SSL.

So the short answer is: Client-side hashing is rare because people use SSL instead.

There are still some potential benefits of client-side hashing:

  • Some software doesn't know if it will be deployed with SSL or not, so it makes some sense to include hashing. vBulletin was a common example of this.
  • Server relief - with computationally expensive hashes, it makes sense for the client to do some of the work. See this question.
  • Malicious admins or compromised server - client-side hashing can prevent them from seeing plaintext passwords. This is usually dismissed because they could modify the JavaScript and disable hashing. But in fairness, that action increases their chances of being detected, so there is some merit to this.

Ultimately though these benefits are minor, and add a lot of complexity - there's a real risk that you'll introduce a more serious vulnerability in your attempt to improve security. And for people who want more security than password, multi-factor authentication is a better solution.

So the second short answer is: because multi-factor authentication provides more security than client-side password hashing.

  • 1
    What if, the server has been compromised by a cracker and he'd like to gather plain passwords from clients to use them at other places? No safeguard but client-side hashing. Why must we force clients to trust the server? – Константин Ван Feb 4 at 7:16
  • @КонстантинВан - please refer to the "compromised server" part of the answer – paj28 Feb 4 at 10:04
  • 1
    Another drawback of client side hashing is that you cannot enforce password policy on the server. Basically you cannot validate that the user selected password is strong enough – Michael Apr 16 at 6:24
44

To understand this problem, first you have to understand why we hash passwords. It is completely possible to store a password in plain text on a server and simply compare the password transmitted to the password received. As long as the password is protected in transit, this is a secure means of authentication (shared secret).

The reason that passwords are hashed is because the problem isn't the authentication, but the storage. If the server is ever compromised, the attacker would immediately have access to all user accounts as they would now know the secret used for authentication of the users.

Hashing acts as a barrier to this. Since the server doesn't know the actual input required to authenticate, even a compromise to the DB does not grant an attacker access to the user accounts. They would still need to figure out the input to give to reach the hash values the application checks against. Sure they could alter all the values to something they know, but this would rapidly throw up suspicion and the system would be shut down and secured.

So, the problem with client side hashing is that it effectively makes the result of the hash the password rather than the password. There is nothing to stop an attacker from bypassing the official client and simply sending the finished hash to the server directly. It provides no additional (or loss) of security during the authentication, but under the situation that hashing is designed to protect against, it offers nothing since the hash stored in the DB is actually the shared secret transmitted to the server.

That said, there are two notable thing client side hashing does give you. While it doesn't help protect your system at all, it may help protect your user. If you are insecurely transmitting the password or the transmission gets compromised without the client code getting compromised, you will still protect the user's password (which they may reuse on other sites) from being leaked.

The other is that you can provide additional iterations of a hash to make an offline attack against the DB more difficult without having to use server cycles (while also extending the length of the "intermediate password that the client submits"), but you still need sufficient server cycles to protect the lengthened password against a rogue client. Again, the primary protection this offers is preventing the original password from being discovered but does nothing for helping protect the authentication mechanism of your site.

Put another way, while it does provide some minor protections, from the point of view of the server, the client side hash should be treated as if it was the user's direct password. It provides no more or no less security on the server than if the user had directly given their password and should be protected as such.

If you want to be able to provide that extra level of security, I would recommend two hashes. Hash once client side to build a new, unique password, then hash that password on the server to make a value you store in the DB. This way you get the best of both worlds.

For the most part, SSL is trusted sufficiently to protect the exchange that the initial hash prior to transmission is seen as unnecessary though and a compromised server could always alter the code sent to the client such that the initial hash isn't performed. It simply isn't an effective alternative to SSL and doesn't offer enough additional advantage to be worth the costs and complexity.

  • I need to encrypt some data client-side, and by sending only the hash to the server, I can proof that the server cannot decrypt the local data, since it doesn't know the plain-text password. Also, when salting the hash with the domainname, there is a garantuee that the server can never leak my password, just a salted (useless) hash. – Muis Mar 18 '14 at 13:46
  • 4
    @Muis - my point is simply that you should treat the hash generated client side as if it was the user's own password when dealing with it server side. It isn't bad to use a client side hash to protect the user's password from being exposed to the server, but it practically acts like the user's direct password as far as the server is concerned. – AJ Henderson Mar 18 '14 at 13:52
  • 3
    Why not simply do both then? Hash on the client side to avoid leaking the actual clear-text password and hash again on the server side to avoid the hash-becoming-the-password problem. – Xaser Aug 27 '16 at 8:29
  • 2
    @uhfocuz No. Not at all, for a great many reasons. The primary issue is that for login purposes, the client side hash would be the user's password, not whatever the user types, as the server can't verify what the client side did. Further, without protection on the channel providing the content of the page, a man in the middle could simply strip the client side hash entirely and capture the user's password. Finally, even without these issues, unless the password represents the same degree of entropy as the key used in SSL, it would be easier to brute force a hash collision. – AJ Henderson Aug 28 '16 at 5:19
  • 1
    @uhfocuz that's my point. It doesn't provide a more secure medium. Two different hashing algorithms doesn't really matter. I never said you couldn't do a client side hash, just that the nature of a client side hash really doesn't offer you much of anything in terms of security. It only protects a user that is using the same strong password in more than one place from having the password sent to the server. That's a very limited advantage for quite a lot of work and potential increased xss surface area. – AJ Henderson Aug 28 '16 at 17:45
21

If you have quite a few advantages, then you should list them in your question so that people will find out whether they are truly useful (and you may become famous if so ;)

People don't favor client-side hashing because they have better ways of protecting users private information. Let's think about the places with potential information leaks and there are three of them:

  • The client.
  • Between the client and the server.
  • The server.

Then let's see why or why not client-side hashing will help in these places.

  • The client.

    If there are malwares on your own computer, for example, if your browser is compromised or your computer is implanted with key-logging software, client-side hashing doesn't prevent a hacker from getting your password. The reason is obvious.

  • Between the client and the server.

    There is the communication channel between client and server. If there is an eavesdropper listening for the communication, then client-side hashing can make the leak of password more difficult because the eavesdropper has to recover the original password from its hash. It's indeed useful here.

    However, this vulnerability is based on the presupposition of an insecure communication channel. In reality, there are protocols whose existence tries to solve this problem exactly. Their major task is to establish a secure channel over an insecure one. The most famous and widely deployed example is SSL/TLS, and it provides more functionality and better security than client-side hashing.

    The conclusion is that client-side hashing is helpful in the channel, but here are better tools.

  • The server.

    Users information may be leaked on the server if the server is compromised by a hacker. The hacker can fetch user passwords from database if they are stored in plaintext. That's why today most servers don't do that. Instead, they store hashes of passwords so that hackers can't easily restore the original passwords from their information at hand (i.e. hashes).

    You may be tempted to believe things still work well if the server simply stores hashes computed on the client side. But this is severely wrong. In that situation the hashes themselves become password equivalents. The hacker can pass authentication by simply handing over the hash without reversing it. The goal of a hacker is not reversing a hash, but breaking into your account. The importance lies in the server's verification process on client data, not on the fact that the data is a hash value. Therefore the benefit of client-side hashing is trivial here and the server must rehash anyway.

To summarize, client-side hashing is helpful in protecting user information, but the protection largely applies to the communication channel. Since we have better approaches there (SSL/TLS), the application of client-side hashing is greatly surpressed. It's simply not the best tool for the task at hand.

  • 22
    Re: this statement: "The goal of a hacker is not reversing a hash, but breaking into your account." I would say that depends on what the site is. Oftentimes the user's password is more valuable than access to the site, with the hopes that the password may be used on other sites where gaining access would have more value. – TTT Nov 29 '16 at 15:00
  • @TTT From its context, this sentence actually means the hacker doesn't care about whether it's a hash or a plaintext password as long as he gets the private information he wants. – Cyker Nov 30 '16 at 2:39
  • 1
    This answer is super helpful. – NDiaz Nov 30 '16 at 19:31
  • 6
    I agree with TTT. I disagree that it is "better" (as you've said) for the client to send their password in plaintext instead of a salted hash. This opens up the risk that some server-side agent steals or leaks the client password, either by malicious intent or negligence. Since many users re-use password cross-side, it's a very concerning risk. – Jay Sullivan Dec 24 '16 at 2:32
  • So the summary of your answer is "because I see only slight advantages"? Not because there are any disadvantages of doing only a fast hash on the server and the slow hash on the client? I elaborated a little on the topic in this answer and am curious to hear your thoughts. – Luc Jan 9 at 23:30
6

What advantages would client-sided password hashing have?

Well, the password wouldn't be sent over the net in clear-text. But you should really be using TLS encryption when you log in, so password sniffing should not be an issue.

Another reason could be that you don't want the server to ever be aware of the users password, not even for a microsecond. That means you give the server the password hash on registration and then log in using that password hash. Unfortunately this doesn't solve anything: The shared secret to log into the account is now the hash, not the password. When you obtain knowledge of the hash, you can log in without knowing the actual password (because the server doesn't know it either).

  • 1
    The advantage for me would be that I can use the user's password to encrypt some local data in my app, and proof that the server is never able to decrypt that data (since it only knows the hash). Otherwise I would have two prompt the end-user for two different passwords (1 for login, 1 for encryption). – Muis Mar 18 '14 at 13:41
  • @Muis In that case the answer would be "Because nobody has such exotic requirements like you do". – Philipp Mar 18 '14 at 13:54
  • @Muis, your definition of "proof" must be weak as often knowledge of the hash is equivalent to knowledge of the password since dictionary attacks are so successful. I do see your point though. It is proof if the user picks a good password. – mikeazo Mar 18 '14 at 15:30
  • 8
    @Muis That's not how salting works. Salts only protect against precomputed rainbow tables, not against dictionary attacks. – Philipp Mar 18 '14 at 16:01
  • 1
    @Philipp, salt does guard against dictionary attacks where the attacker just wants one out of many captured hashes. It does not help against dictionary attacks on a single hash. – mikeazo Mar 18 '14 at 16:53
6

It is good practice to hash on the client side, then salt the password and hash again on the server side. This is an extra layer of protection against man in the middle attacks. SSL is the first layer however Snowden's revelations made it clear that SSL can be compromised by organisations such as the NSA with relative ease.

  • 4
    This answer provides nothing that the other answers don't, and misses the point that to a MitM, the client's hash of the password can be used as if it were the password itself. – Mark May 5 '15 at 8:29
  • 3
    @Mark Um no Mark. This does indeed help with mitm. Mayhem is stating at hashing the hashed password yet again. – Karl Morrison Jan 28 '16 at 22:02
  • This is a good idea I haven't thought of. Hash on the client side to hide the plain-text password, then hash on the server side to protect from a server-side breach. Thanks for sharing! – Aaron Gillion Apr 15 '16 at 23:55
  • 1
    @Karl, The 'man in the middle' would still be providing the same request parameters as the target user. Just because it isn't a password, doesn't mean the attacker can't intercept the hash and provide that same hash on to the server (to let it "hash the hash" and succeed at a match). – zyglobe Oct 26 '16 at 3:25
  • @RedGlobe That however is true. But it does help, because a looot of internet users use the same password for everything. I agree it might not help against that particular system, but it will help on a broader scale. – Karl Morrison Oct 26 '16 at 8:48
3

Since you are talking about web application...

In a database we have a table call dbo.useracc we are storing these hashes password

User        Password
--------       ----------
user1       5f4dcc3b5aa765d61d8327deb882cf99
user2       202cb962ac59075b964b07152d234b70
user3       098f6bcd4621d373cade4e832627b4f6

and our login function in web application be something like

if (user == $user and password == $pass) {
           return auth.token
}

Let's say an attacker successfully hacked and stole the database and saved our dbo.useracc data. He now has our hashed password.

If your login hashes process is stored in the client, the attacker can still accesses your account with the hashed password by just hooking up the HTTP POST method altering the password field to send your hashed password and he is still able to login. Remember your application data are communicating with the server through the POST method eventually after it's hashed to be checked against.

However if the hashing process is in the server, it's another story.

$pass = md5.hash($pass);

if (user == $user and password == $pass) {
           return auth.token;
}

If the hacker use the hashed password to login, it will be a hash 'hashed password' checking against a hashed password.

In this case let's say the attacker post

$user = user1 $pass = 5f4dcc3b5aa765d61d8327deb882cf99

After the server side doing $pass = md5.hash(5f4dcc3b5aa765d61d8327deb882cf99) it will return '696d29e0940a4957748fe3fc9efd22a3' which is returning a false statement.

This is to fence off attacker who has successfully stolen the database data and trying to access through the web application using the hashed password. And of course the attacker still can hack into the accounts if they successfully bruteforce / crack the hashes through dictionary attacks and so. However the hacker requires longer time if the password is a good password after compromising the system and the server admin could just reset the password and email the users.

Also it is also used to internal threats like employees in an enterprise. In an enterprise, there will be Database Administrator and Developers. They are different roles. Now to prevent the employee users to access to the sensitive data, they need to have access to both application and DB to get access to the data. Of course you might argue a DBA can still alter the database data through the database itself, but it is not accessible by the developers and it is easier to pinpoint where is the attack from. It is about access control rights and minimizing the risks and threats.

  • 1
    You're correct that it doesnt make it harder for an attacker to enter MY site using the stolen hash, but it makes it harder to login to ANOTHER site, since the other site most likely dont use exactly the same salt + hashing algorithm. – Muis Mar 18 '14 at 14:04
  • There's no way the attacker can access ANOTHER site with the hashed password too as long as the ANOTHER website don't practice hashing in the client and is a good password that is hard to be bruteforce by dictionary or rainbow table attacks. And as a developer, why would you even care about "ANOTHER" site in the first place. If the users value their other data a lot, they should practice not to use a global password instead. – Sky Mar 18 '14 at 14:11
3

Though the topic has some concrete leak points, as pointed out by @Cyker, the discussion is a little brisk here ... I'd like to add one point that I didn't see mentioned.

It's simply that if you hash ASAP, then you reduce the programming risks of accidentally passing a clear text password somewhere that it shouldn't go. We already take measures like secure strings and secure arrays to try to destroy the clear text ASAP; and hashing at the moment that you get the password is another measure like that ... As code evolves, etc. the risks seem to still be reduced.

I just wrote a little C# "Box" that takes the SecureString clear text and hashes it immediately --- this way I simply know that it will never be logged or passed to a library I don't expect. This is not so much about a protocol as it is just the programmer here sitting and looking at a password --- I don't wan't to touch it! (It's still a password equivalent in some aspects, but it is at least immediately concealed from folly like moving a closing parenthesis in a chained method call and passing clear text to the wrong place. And a secure array is still not concealed.)

1

I agree that if SSL/TLS is available the advantage of client-side hashing to protect the authentication process is limited. However, SSL / TLS does not resolve the vulnerability to custom hardware attacks if the attacker has access to the stored hashes (AFTER the process). Functions such as simple salted hashes or schemes like PBKDF2 are very vulnerable to these attacks because of their low memory requirements. The cracking of passwords, protected with theses schemes is cheap and fast. And that is at least one of the main problems of password hashing.

At first glance, this has nothing to do with client-side hashing versus SSL/TLS - but: When a sever implements a memory-hard password hashing scheme such as Scrypt, Argon2 or Catena to protect custom hardware attacks, the server‘s hardware requirements increase dramatically. In reality, services therefore reduce the memory-hardness or switch to vulnerable schemes. Client-side hashing helps a bit to get around this problem. When the clients compute these expensive (memory hard) functions, the service can use them without the need for better hardware.

Modern password hashing schemes therefore offer the possibility to delegate the most expensive (memory-hard) parts of the function to the client. This feature is called server relief and is offered by Argon2 and Catena.

Conclusion: Using modern password hashing schemes, which are much less vulnerable to custom hardware attacks, will increase or at least should increase the use of client-side hashing in the future – of course along with SSL/TLS.

0

I'm going to jump in here with the express purpose of weighing in favor of the client-side hashing mechanism. Let's see how this benefits us:

Client-side: No improvement.

In transit: Protects the password in case of SSLstrip in which the password ends up being transmitted in cleartext. However, if HSTS is implemented, then most people would say that SSLStrip would have no effect. Right? No.

On entry to the server: Finally, we see the major benefit. What happens if someone has compromised the server? They get a continuous flow of cleartext passwords if they just boot up Wireshark/TCPDump and export the server's private key. Now they can sit on the wire for a couple of months, and for high-volume servers (millions of user registrations per month), they get their massive plaintext breach. This is assuming that it is more valuable to grab the passwords for the people on the service than to have RCE on their server, of course.

On the server: Performance benefits if it doesn't have to run bcrypt on every incoming password, which offloads some computational cost onto the client without introducing any new vulnerabilities. This seems to be a good thing for your server's administrator as well as your hardware costs.

Still, it looks like best practice would be to incorporate password hashing into the client side unless it creates unbearable page load times for the users.

  • I am curious to hear why someone downvoted this answer. SSLStrip is a little dated, but not wrong, and the rest of the answer sounds accurate to me. – Luc Jan 9 at 23:33
  • I certainly don't know. Re-reading my commentary from several years ago, I can't see any obvious flaws in my reasoning. – DeepS1X Mar 13 at 6:03
-1

I think client-side hash has one upside and one drawback:

pro : You hide the password in case of dns/phishing/whatever, which is useful for the user, since most people reuse passwords on several service. As other devs said, this does nothing for your own security.

cons : Your server does not get the password, which prevents stuff like warning the user about password strength. I know some will say this can/should be client-side, but when you have multiple clients, this can be nice to centralize server-side.

  • (I did not downvote, would be nice if people could explain downvotes.) Password advice should really be done client-side. I would recommend a library like zxcvbn which is available in many different languages and seems very goal-oriented and well-designed. That would also limit having to incorporate the advice in all clients' code separately. – Luc Jan 9 at 23:34
-5

i think the probability of being hacked in client-side is more higher than that in server-side. (Because there are some IT expert look after the server) . if your computer is already being hacked. the client-side 's algorithms which used for hashing your password also can be stolen by hacker . Aso soon as your algorithms is no longer a secret. i think,it become useless.

  • 3
    We generally frown on secret algorithm (See Kerckhoffs's principle and security-through-obscurity. Password hashing certainly doesn't need to rely on this. At most we apply a key and hope that the attacker doesn't find even if they manage to steal the database. – CodesInChaos Mar 18 '14 at 11:03
  • The "server is more secure" argument makes little sense in this context. 1) The client knows the plaintext password, so a trojan can trivially steal it with a key-logger. 2) Password hashing only offers an advantage over plaintext passwords when the server gets hacked and the database gets stolen. – CodesInChaos Mar 18 '14 at 11:05
  • danke,CodesinChaos. you offered me a useful lesson for free. – Li Billy Mar 18 '14 at 11:14
  • 3
    The way twitter works is that you follow people whose tweets you find interesting. No need to ask for permission. – CodesInChaos Mar 18 '14 at 11:20
  • 1
    A server with all its user data is a way more valuable target than one single user. – Gumbo Mar 18 '14 at 14:33

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.