2

In most protocols I have encountered in which a passphrase is used for authentication it is stored not in plaintext, but a PBKDF digest of it instead. This is obviously good.

However what does not seem to be standard practice is to compute this PBKDF digest on the client-side while registering/updating a passphrase. Instead, it is often sent to the server and then the user is left to only hope they handle it properly.

Why is this so? Am I missing something?


EDIT: Because this was unclear to some, I don't mean to suggest the server-side should not hash. The server should. I'm asking why it's common practice to not hash client-side at all.

orlp
  • 391
  • 2
  • 16
  • This post is relevant: http://lists.webappsec.org/pipermail/websecurity_lists.webappsec.org/2014-January/008967.html – paj28 Mar 23 '14 at 11:04

4 Answers4

4

I think the main issue are the client side languages (normally JavaScript), they are relatively slow. This would often lead to fewer hashing rounds and therefore weakens security.

If your client side language is fast enough, you could calculate the expensive PBKDF client side, then calculate a cheap hash on server side (SHA512 for example). To get the plaintext passwords an attacker still had to calculate the slow PBKDF. It is also not possible to use the PBKDF directly as password, because only the hash of the PBKDF is stored (the output of a PBKDF2 can be seen as a very strong "password", so it is safe to use a cheap hash function).

One downside is, that the handling will become more complex, you need to send salt and cost factor to the client for verification of the entered password. Another problem is to ensure integrity of the client side code, if somebody could alter the delivered JavaScript code, he could return a known string and you would store the now unsafe PBKDF.

martinstoeckli
  • 5,279
  • 2
  • 29
  • 32
  • 1
    Why was this downvoted? This seems like a perfectly reasonable answer. – Levi Mar 21 '14 at 16:32
  • 2
    Follow-up: I see some other discussion that it's easy to reverse-engineer hashes, and that's why PBKDF2 is used in the first place. This is not correct: hashes are assumed to be difficult to reverse (see "preimage resistance"), so attackers are required to fall back to rainbow tables or brute-forcing the input. Since rainbow tables don't work for high-entropy input (such as the result of a PBKDF2 operation), the attacker must brute-force the hash input, which is equivalent in cost to brute-forcing the PBKDF2 result. – Levi Mar 21 '14 at 16:54
  • It's not that hashes are bad, it's just that PBKDF is better. Well, tbh un-salted hashes are bad, as is evident from some recent breaches, so at least use salt. – xkcd Mar 21 '14 at 17:29
  • @xkcd - What Levi tried to explain is, that it is absolutely safe to store an unsalted non interated hash, if the "password" is strong enough. Salting and key-stretching is necessary, because people choose relatively weak passwords, which they can remenber. The output of a PBKDF2 on the other side is a very strong "password", and can be hashed with a hash algorithm like SHA512 even without a salt. – martinstoeckli Mar 21 '14 at 21:12
  • @martinstoeckli - Thanks for the clarification. Yes, he is right then of course, but confusing terminology ... I didn't get password = input :) – xkcd Mar 21 '14 at 22:18
  • Note that 1) the "client side integrity" issue is just as bad for server side hashing. 2) The client has longer time limits for hashing, this can compensate for slower code. With fast code it allows stronger hashing compared to server side hashing. – CodesInChaos Mar 23 '14 at 11:25
0

I realized that this was brought up long ago, but here's my take anyways. If KDF processing is done on server side, then the sysadmin of the server is to be considered within the adversary model, as he/she could manage to somehow sniff process memory and learn clear text user passwords. In my eyes, this scenario (malicious sysadmin after some sort of impersonation attack) might be more common/feasible than the one when the attacker grabs a copy of the authentication database of KDF processed credentials. Just my two cents.

Bdab
  • 1
  • OTOH if the sysadmin is competent enough to do that he should have no problem just changing the javascript that gets sent to the browser. The case for client-side KDF is a bit stronger for native applications, but you still have to trust the developer. – AndrolGenhald May 14 '19 at 18:32
0

Look at it from two extremes:-

  1. Server is using PBKDF properly

    If the server is doing PBKDF properly, it would be a useless duplication of effort and resources if you do the same thing on the client-side too. You will have to implement or use a client-side software that will run PBKDF on your password and then send that to the server, and the server will then run PBKDF on the out-put of the client-side PBKDF and store that in its database. I hope you can see the use of the additional resources without any additional benefit.

  2. Server is not using PBKDF at all

    So if the server is storing passwords in plaintext, the output of your client-side PBKDF will be stored as it is on the server. So when an attacker steals the server database, it won't make a difference if your password was PBKDFed on the client-side, to the server (and the attacker) it will be exactly same as a plaintext password like hunter1 :)

So to answer your why, the general principal is that its the entity that is controling the resource that is responsible for its security, which in this case is access control. Or as a saying in my mother language, "the thirsty man has to go to the well, the well doesn't come to the thirsty" :)

xkcd
  • 761
  • 4
  • 10
  • I disagree with scenario 2. If your database gets leaked and all passphrases were processed client-side, then the attacker will only get digests, and never gets to see the actual passphrases. This is very important as passphrases are often re-used between websites, or contain personal information. – orlp Mar 21 '14 at 14:35
  • 1
    They do not know the password for your other sites, but they can no gain your authorizations on that site since they can just replay back the value they now have. E.g., they compromised the db, but not the app, now they can just use the app as a normal user. – Eric G Mar 21 '14 at 14:49
  • @nightcracker To better understand scenario 2, think that when you created your account on the server, lets say via a web form, did you write your password in the form or its PBKDF digest? If you wrote your password, the server stored your password in plaintext. If you wrote the digest, the server stored that in plaintext (plaintext meaning without any change). Whether it was the password or the digest, the server checks only that to allow access. So it doesn't matter whatever you do on the client-side, the server (and attacker) are only interested in what is there in the server database. – xkcd Mar 21 '14 at 15:57
  • @xkcd - If you had calculated a server side hash, then even with the hash-values (from SQL-injection for example) you could not login. If you store the client side hash directly, you can login as soon as you know the stored hash-values. – martinstoeckli Mar 21 '14 at 16:06
  • @martinstoeckli - You are right, as long as the attacker doesn't know other parameters like salt, PRF and c etc. used on the server side. But I didn't cover this scenario in my post, I was just giving the two extreme cases on the opposite side of the spectrum to show why this is not done. – xkcd Mar 21 '14 at 16:17
  • @xkcd You have not considered the actual useful scenario, where both sides hash. Client-side uses PBKDF, server-side uses a regular hash. And you make it seems as if a potential attacker is only interested in getting authorization for this particular application, while I think that any attacker would value raw passphrases a LOT more than just auth digests. – orlp Mar 21 '14 at 16:19
  • @nightcracker - Sorry, I don't get you. You mean that the client stores the PBKDF of the password and the server stores the hash of the password? Can you please clarify more? – xkcd Mar 21 '14 at 16:23
  • @xkcd The client uses a PBKDF on the password before sending it to the server and the server hashes the PBKDF digest before storing it. – orlp Mar 21 '14 at 16:33
  • @nightcracker - Ok, in this case scenario 1 still applies. For the server, the PBKDF digest is esentially a passphrase and if it is hashed without salting, then its not very secure. If you just want to protect your passphrase, the attacker doesn't get to know your passphrase, but your account access can still be compromised. Usually account access is of much greater value than the secrecy of your passphrase (assuming its not a universal passphrase :)).

    All in all, just the normal PBKDF on server is enough, both your passphrase and account access will be safe.

    – xkcd Mar 21 '14 at 16:41
  • Your scenario 2 doesn't make sense. If the client uses a slow hash (PBKDF2 etc.) and the server uses either SRP or a cheap hash, then gaining access to the database doesn't do more damage compared with server side PBKDF2. 2) Why are you assuming the client side PBKDF2 is unsalted? That'd be plain dumb. At minimum one could use username+servername as salt, but transfering a random salt isn't hard either.
  • – CodesInChaos Mar 23 '14 at 11:22
  • @CodesInChaos - That's why I said extreme. There can be a lot of scenarios but I used the two extreme ones on the opposite sides of the spectrum as examples to try to give an insight to why this is not done on client-side. Apparently I have failed :) – xkcd Mar 24 '14 at 13:40