One of the companies I worked for used client-side hashing to minimize risk when logging the password in the server logs. Can this be a good reason to implement client-side hashing?
As others have pointed out, this just replaces "SECRET" with "HASH(SECRET)". To make things worse they log the hash, which is now the password.
This is because the client is authenticated on the basis of the hash it transmits, alone; so, knowing this hash either by intercepting it at the client level or by lifting it off the logs, one can access the service at any future time until the secret is changed.
These two things together negate all logging security and create a problem (you are now logging "data, including personalised security credentials which can be used to carry out fraud", and this impacts your PSD2 compliancy).
Having a different hash on the client (for logging purposes) and on the server (for authentication purposes) would be tricky to implement, since the server guys would have no quick way of verifying that the hash is indeed correct, unless they knew the password (which would have to be stored in the clear somewhere). Using the same hash or a two-level hash might be used, I don't know, to diagnose whether the password was sent correctly (the client sends both the pass and its hash, the second gets logged and is the same as the hash stored in the auth records, or is the hash of that hash just to complicate things) -- but unless things go very wrong, this information is the same as the login status.
A better way to do this would be for the server to send a unique ID plus a timestamp, and for the client to hash together the password, the unique ID and the timestamp. The server could then send ID, timestamp and username to a black-box "oracle" that would only answer yes or no (or "OK", "NO SUCH USER", "BAD PASSWORD", "TIMESTAMP EXPIRED", "UNIQUEID REUSE DETECTED" and so on). This way:
- the server does not know the password (the "oracle" does)
- the log can safely contain both unique id and timestamp
- the hash cannot be reused (the timestamp would go "stale" after some time)
- the password never travels in the clear, only the hash does
- unique id and timestamp act as salts of each other
You might be interested in looking at thinbus-srp.
Sending hash instead of password does not solve the problem with logs. If an attacker get access to logs and can read hashes, then knowing password becomes not necessary. In the login request the attacker will just send the hash retrieved from the log. The server will not know if the client has password and created a hash, or if the client knows only the hash.
No, that's not a good reason:
This never helps. This architecture just replaced the secret "password" with the secret "hash of password". Neither can ever fall into the wrong hands, because the hash is sufficient for logging on. (You can never assume the client has unmodified software. A simple debugger is sufficient to make a client program send whatever you want.)
And they're logging these hashes, which they simply shouldn't do, because now they've got a plaintext log of all the credentials necessary to log on.
The issue at hand is the overzealous logging, not the passwords.
Plain hashing, as far as I can tell, also doesn't ever contribute any further factors into the credentials, so I only see very strange use cases where it might be helpful (for example, to avoid password reuse vulnerabilities should the server be compromised—but if your user reuses passwords, then your server being compromised should be the least of their worries). Instead, I often see it used as snake-oil ("magical cure") for security issues that are much more severe but people try to distract from—exactly like this logging issue, or things like unencrypted database connections.
First let me say that you should never ever be logging passwords, but it seems from the question that the company you worked for was worried about inadvertent logging. Maybe they have some kind of logging software on their server that stores all communications including when you send the password.
Simple hashing offers a very small level of gain. As others have said if your client uses the hash to login, others could use the has as well, so what's the point? The very small gain in security is that you won't automatically expose the raw password. This would only help if:
- The password is large enough to prevent discovery from the hash (using rainbow tables or brute force for instance)
- The password is changed regularly (hash would only be usable for a short time)
- You log the passwords WHICH YOU SHOULDN'T EVER EVER DO, but from your question it seems you are worried about an accidental occurrence or if some third party or crash/error reporting software logs it carelessly
First: If someone nabs your log file and you have plaintext passwords in there, it's just game over. Some software might log what is sent to the server without your knowledge and the log file might be placed somewhere it shouldn't be. Yes, in a perfect world this would never happen, but some temp or tech support person might run across such a file some day. If there are plaintext passwords in there, the amount of work to do something malicious is just so small it could tempt people that would never dream of cracking hashes or writing software to use your system with a hash. "My manager's password is there? I'm just going to login to our email client with his information quick and search for my name for what he's been saying about me..."
Second: If passwords are changed regularly, an uncrackable hash would be worthless in a few months, or on other sites. Many people only make minimal changes to their passwords though, and re-use them on other sites. So if your software that uses client-side hashing exposes your application because the hashes can be used, the same hashes probably can't be used for other purposes such as email or authentication to network shares or other intranet sites. Some people probably have the same or similar passwords for other sites online like personal mail, amazon, banking, etc. It's bad practice, but that's what a lot of hackers rely on. If you see the password three months ago is 'Fluffy#$Kitten7', you might try 'Fluffy#$Kitten8' next since many people make minor changes to their password when they are required to change it frequently. The hash would be completely different for the new passwords so the old one would be invalid.
You have two issues here: logging sensitive data in plain files, and password hashing.
Logging sensitive data
Don't do this.
This includes passwords, other security tokens (session IDs), racial or other data labeled as sensitive under GDPR or your local jurisdiction, and other data that sysadmins don't need to help in debugging.
If you have a stupid manager that overrules you, then look into encrypting the data with a public key. The private key can be kept somewhere safe, like in a safe deposit box or some offline system. If you ever need access to the data, you can get it, but there is very little risk of anyone else decrypting that data.
Specifically for passwords: if you are going to hash them anyway, then why log it in the first place? Apparently nobody wants access to the plaintext version of it, and to reset a user account you can reset the password value in the database. There is no reason to log hashed passwords.
To see whether client-side hashing is helpful, define what the risks are and follow the logic.
You mention an insider threat, but who is that insider? Can they only read log files? Do they have database access? Can they change the code running on the server?
If the insider can only read log files, then client-side hashing would help. If the user uses Fluffy1992! as password, then hashing prevents the insider from knowing that, so the insider can't try to login to other accounts of this user. But like others pointed out, they can login to the application by submitting whatever the original user submitted (a replay attack; this can be prevented with a challenge-response system).
If the insider can also access the database, there would be no reason for the insider to login to the user account: they can already see and modify everything the user can. Hashing still helps not to reveal the kind of password that the user used, so it's still helpful.
Note that the server should always apply a quick hash to the hash that the client sends: if someone gains read-only database access (e.g. SQL injection in a
select query, or a stolen database backup), they can read the password hash from the database but still need to break it. Without applying the hash on the server, they could take the database value as password. So the client should do
pwhash = bcrypt(password+salt,cost); send(pwhash); and the server should do
Since your question is about logging the hash, I think the simple solution is not to log sensitive data, as said. Nevertheless, client-side hashing is not a bad idea if you also apply an additional hash on the server. Client-side hashing helped mitigate other security issues in the past, but if it had been more common, it would have prevented many more.
It does not, proper hashing requires iterations and salts, which with client side hashing can't be achieved (e.g. without the system knowing the salt and actual password it can't verify it). If you are just doing a normal hash, then you just replace the secret like Marcus is pointing out.
However the proper way of fixing is - is to use tokenisation or sanitisation of passwords within the logs, rather than using hashing. Tokenising and sanitising should be done for all sensitive fields ideally.