last day (28 days later) » 

17:31
56
A: Why is client-side hashing of a password so uncommon?

AJ HendersonTo 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 o...

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 my point is that the salted hash isn't useless. It can compromise the integrity of your authentication system as it is the new password for authentication (even if not for encryption). The attacker could still get the hash from the DB on the server and convince the server that they are the user and access the encrypted copy of the files (which granted, they may have access to already anyway at that point). Additionally, a salt should be globally unique, not a domain name.
@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.
My main worry is that the leaked password can be used to login to OTHER sites, where the customer used the same username/password combination. This will be prevented by adding the domainname to the hash (since I cannot store an unique value persistently in javascript).
@muis the salt need not be protected. Store it on the server and send it to the client before hashing. If the server can't be trusted for this, still use the domain name and user name appended to the server supplied data perhaps.
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.
17:31
@xaser - you could, but it wouldn't add much. That's basically what muls and I were talking about in comments. It only comes in to effect if you have a man in the middle that can only observe (otherwise they could strip the client side hashing) and only makes a difference if the salt is globally unique (can't be rainbow tabled) and the password itself is secure enough to resist being brute forced with a hash cracker. It does not protect the site itself as the client side hash IS the user's password for that site and only would protect shared passwords (which are bad anyway).
Does hashing on client side and on server side not provide just as effective security as using SSL/TLS to transmit passwords in plaintext. If not even more secure if these protocols were to be broken? Length is not considered here, complex passwords could be a requirement if needed @AJHenderson
@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.
@AJHenderson what if the "hash being the users password" is providing a more secure medium, and two completely separate hashing algorithms were used on client and server side. And just to appease you, SSL is also being used here. Would this be an okay dynamic for secure client side hashing, while also keeping the nature of the hash securely stored on server side.
@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.
@AJHenderson I still am strongly opposed to your claim that this would provide very limited advantage, it would double bruteforcing times, never could the real password be easily divulged in the scenario our HTTPS protocols are already broken, and XSS, no, tampering, yes but this data originates to the registration, would be just as effective as really using tamper data
17:31
@uhfocus it would not have any impact on brute force time that extra runs server side wouldn't have and provides no advantage at all to the site implementing it as the client side hash is irrelevant to the authentication. If ssl breaks the system offers no advantage at all as it does not provide any integrity check or server authentication. The only advantage it offers is the one I described. If it provided what you describe it would be great, but it doesn't.
We can keep discussing this in chat here if you want.
@AJHenderson I don't think you'd want the server sending the salt to the client. Salt helps protect against the shotgun approach, determining the password for many users at once, if the database is compromised. It doesn't help defend against an attack against a single user. Leaking a user's salt publicly to anyone attempting to log in with that username would slightly decrease their overall security.
@lordcheeto how? Without the database data, an offline attack isn't possible. Having the salt without the hash is of zero value to an attacker. This is why the salt isn't considered secure data. The DB must know it and if the attacker doesn't have the DB (or atleast the hash), it is completely useless information. If the client itself is compromised they can simply key log.
Luc
Luc
"If the server is ever compromised, the attacker would immediately have access to all user[s]" Woa, big surprise! Someone who owned the server can actually access things on the server! Sarcasm aside, I feel like this answer does not highlight the right things. Sure, one should do a fast hash on the server, but why else do we bother with slow hashes and salts if not for the user's protection? Client-side hashing has many advantages and I consider preventing a login to be a nice side effect that is by no means essential for system security.
@Luc - not all breaches involve total control. If just the user table is accessed in a readonly mode, all users would be breached fully. If the hashing is secure server side, there would be a sizable effort per user still in order to be able to compromise the system further. Perhaps just an offline backup server is compromised or a backup on a development laptop is stolen. It's foolish to only expect all or nothing breaches. A slow client side hash is trivially bypassed as the client side can be skipped and simply enter the result the server expects instead.
@Luc - note that I actually agree with your answer on the other question as it is dealing with an application. In the case of an application, it's at least slightly harder to bypass the additional hashing to skip straight to the intermediate password, so there is some value, but this question was talking specifically about websites where it is trivial to skip to the intermediate password. All client side hashing does for a website is make a password derived password and a slow hash is no more effective than a quick client side hash or a password derived key.
Luc
Luc
@AJHenderson By it being trivial to skip to the intermediate password, you mean that an attacker would just modify the server's code to stop it from sending the necessary JavaScript to the client, so that the client submits the password instead? In that case, see the FAQ at the bottom, it's an argument I frequently see and I just don't think it's enough to negate all of the advantages.
17:31
@Luc - your FAQ is wrong when it comes to websites. Comments aren't a great place for extended discussion, but to be brief, slow hashing ONLY matters if the hashes are compromised (thus the DB is compromised) if the server isn't compromised, things might as well be in plain text as long as channel encryption is in place. The point about a browser extension is completely irrelevant as the attacker is not attacking the user's machine, but rather the web tier. The chances of having a limited incursion, especially when there is decent IDS, is actually quite high.
If things that shouldn't be writing to the DB start writing to the DB, something is going to notice, but there are many possible ways that read only hash lists could be exfiltrated. It would then be possible to start working on compromising accounts for either changing things in the system or looking for matching credentials on other services. That is the much more realistic case and client side hashing isn't going to do much to help. It has value for password extension, but that's all it's really accomplishing.
SSL HAS NOTHING TO DO WITH CLIENT SIDE HASHING. Client side hashing eliminates the Password Policy and eliminates the threat of server leak password cracking assuming the server also hashed the clientside hash.
@8vtwo - yes, and? I'm not sure how you think SSL is related to this answer, other than the bit pointing out that client side hashing provides no transmission security improvement. I went in to other detail about how it doesn't protect against a compromised server either. The only thing it does is allow an extension of the at rest brute force cracking efficiency as you could use an expensive hash to make bad passwords a bit less bad. This is mentioned in my original answer. (6th paragraph)
@AJ Henderson Comment was definitely meant for the answer above this one where I read "as compared to SSL it has a number of weaknesses" (WTF?!) and I went nuts and scrolled too far.
@8vtwo - ah, that makes more sense. :)
@AJHenderson regarding your claim "...Having the salt without the hash is of zero value to an attacker..." --- well, not quite: knowing the salt for a given user potentially allows the attacker to pre-compute a rainbow table for that user such that, perhaps a (long) while later, when that attacker does gain read-access to the database, they could then crack that user's password in a fraction of the time!
@AJHenderson Nonetheless, you could just send a simple "hash" of the actual (128-bit+ GUID) server-salt instead (relegating the attacker to the lesser "pre-compute big list of slow-client-hash(hashed-salt || possible-password)'s" instead....)
@AJHenderson Granted, browsers would still have to implement slow-client-hashing natively (not in JavaScript, although it can be "called" from such) to circumvent the security.stackexchange.com/a/43038/25009 problem...
17:31
@ManRow - if they are precomputing on the hope they'll eventually get the hash, that's going to either be pretty targeted or a wasted effort in many (most?) cases. You are technically correct, but I don't see many situations where that would be a worthwhile thing for an attacker to bother with.
@ManRow sorry, I'm not following what you are trying to accomplish with the simple "hash", so can't really respond to that. Adding a native implementation in browser also seems like a fair bit of work for something that would rarely be used because of the very limited benefit provided. It really only provides protection of the user against the legitimate site or a compromised SSL tunnel, the first of which won't do anything if account passwords are unique (like they should be) and the latter is pretty unlikely in the vast majority of cases.
@AJHenderson Native in-browser implementation may be simple to add (e.g, add argon2 from the libsodium DLL/shared object, and then expose it via the SubtleCrypto API). As this is significantly faster than a pure JavaScript implementation, salted client-side slow-hashing may help save a couple iterations or so of server-side slow-hashing (essentially, offset some of the computation over to the client). Or, perhaps, even to overall increase the computation required to compute the password hashes altogether...
@AJHenderson The purpose of using a hash of a user's server-side salt as the "client-side salt" is simply to prevent an attacker from learning the server-side salt without having a full database leak. Even if they don't know the server-stored password hash NOW (at this present/current moment), knowing just the salt will allow them to create a rainbow table for possible passwords with that correct specific salt -- so that, in the future, if they do gain access to the real password hash sometime later on, they can crack that specific user's password much more easily...
@AJHenderson For example, say Alice wants to crack Bob's password P -- but for now, she only knows his username. Alice enters Bob's username into the app and easily just receives his raw server-side database salt S. There's no database leak of Bob's stored password hash H yet, so in the meantime she "precomputes" a rainbow table of possible passwords P. Later on (sometime later), the database does get leaked -- and then, Alice discovers H!
@AJHenderson Now, she quietly runs her reduction-function over H some number of times, and eventually it coincides with one of the chain-termination values stored in her rainbow table! Now, she's finally ready to compute Bob's P -- by starting from the beginning of that specific chain!
@AJHenderson But alas -- if instead the app sent her some quick Q = hash(S) (rather than S), while storing H = server-hash(S || client-hash(Q || P)), well, then the most Alice can "precompute" in the meantime (before a database leak exposes the real S and H) is a just list of possible C(P') = client-hash(Q || P'). And, even once she later learns S and H at some time (from that "future" database leak), the best she could then do is just an exhaustive-search feeding that list of C values (and other guesses at P) into H' = server-hash(S || C) until a match H' = H
@ManRow - that works for protecting determining the original password, but does not help secure the account. Any client side hashing you do simply generates a derived password. No attacker needs to do the client side hashing as they can directly attack the hash output as the password. It would give some length extension on bad passwords, but that's about it.
As for the pre-computed rainbow table, yes, I understand what it would allow, my point is it really isn't useful. Spending a bunch of time to compute a rainbow table based on individual salts in the hopes you might get the hash from the DB before it is changed (because salts should change with every password change), is going to be a waste of time and resources 99.9% of the time. Also, how is the server side salt getting compromised without the hash itself in the first place?
 
5 hours later…
22:56
@AJHenderson (1) Server-side salts would get compromised without the corresponding password hash if the server-side salt is what the server returns as the "salt" to use for client-side hashing. (2) And how exactly then would attackers attack the client-side "hash output" as efficiently as they would a mere simple plaintext password (as if no client-hashing takes place)? Are you assuming here that there is more than just a server database leak of salts and password hashes going on here?
@AJHenderson For #2, if that is the case, you should state that as part of your assumptions. Since, having "only" just a server database leak of salts and password hashes, with no other security compromises, would still necessitate the attacker to run the salted slow client-side hash algorithm in addition to the salted slow server hash on each password "guess" anyway. This is still more expensive than merely plugging in plaintext passwords into the server-side-hash only.
Not to mention -- even though salted client-side hashes can still be pre-computed offline "before" a database leak occurs, it would still be much more inefficient from a storage standpoint as well. Simple plaintext low-entropy passwords can easily be even generated from a dictionary, but even if they are stored, there's likely quite a bit of compression that can be applied to such a list as well.
But, their client-side hashes, on the other hand, can not only be slower to compute but also less efficient to "store" as well due to a list of hash outputs being much less "indistinguishable from random" and hence likely much harder to efficiently compress/store as well.

  last day (28 days later) »