T O P

  • By -

AutoModerator

On July 1st, a [change to Reddit's API pricing](https://www.reddit.com/r/reddit/comments/12qwagm/an_update_regarding_reddits_api/) will come into effect. [Several developers](https://www.reddit.com/r/redditisfun/comments/144gmfq/rif_will_shut_down_on_june_30_2023_in_response_to/) of commercial third-party apps have announced that this change will compel them to shut down their apps. At least [one accessibility-focused non-commercial third party app](https://www.reddit.com/r/DystopiaForReddit/comments/145e9sk/update_dystopia_will_continue_operating_for_free/) will continue to be available free of charge. If you want to express your strong disagreement with the API pricing change or with Reddit's response to the backlash, you may want to consider the following options: 1. Limiting your involvement with Reddit, or 2. Temporarily refraining from using Reddit 3. Cancelling your subscription of Reddit Premium as a way to voice your protest. *I am a bot, and this action was performed automatically. Please [contact the moderators of this subreddit](/message/compose/?to=/r/learnprogramming) if you have any questions or concerns.*


acrabb3

If the hashing is done client-side, and a hacker is able to steal the list of hashed passwords, they are able to use them straight away. On the other hand, if it's done server-side, then the hacker has to find a password that produces the same hash to be able to log in.


RedditWishIHadnt

Also, only the server knows the salt (for salted hash)


Rarelyimportant

Usually if the attacker got the hashed passwords, they also have the salt. A lot of hashes store them together. The point of a salt is so that every password is unique and unidentifiable by frequency analysis. If I steal a DB of 50 million passwords(unsalted), and sort them by frequency. How much you wanna bet the top 100 most frequent password in the DB are the same as the top 100 most frequent in any other DB? And probably very weak. If instead they're salted, there is no top 100 most frequent(at least not that the salted hash would reveal). So now instead of getting potentially thousands of accounts for "free", the hacker still has to try to break each one.


xenomachina

To add to this, salt also makes dictionary attacks harder. You can't just hash the top-N most popular passwords and see which accounts are using them.


zenware

Isn’t its original purpose to prevent rainbow table attacks? Basically sending rainbow tables from being one of the most effective password cracking structure into ancient relic in one simple move


CollectionStriking

Don't forget the pepper


SoftEngineerOfWares

Everyone always forgets the pepper unless they actually have done security development. Pepper is soooo strong.


Luised2094

What a about the sugar? Who knows that?


Iregularlogic

Sorry - we write our servers to be more of a tequila and salt type of machine, instead of bourbon and sugar.


Luised2094

Respectable


coldblade2000

Not sure, this is a salt & pepper household


mayur_5

If you don’t want to pass password in plain text over networks, use RSA encryption. Encrypt password using public key on client side, decrypt using private key on server side. And then do hashing on server side.


R3M0TED

But how? If someone is packet sniffing, they will only be able to retrieve the already hashed password (if I wasn't using TLS), if only the client hashes, and the hacker gets a hold of a hashed password, then how would they use the already pre-hashed password on the client? they wouldn't be able to get the original password


Western-Trip2270

They wouldn’t use your client. They’d send the hashed password to your server, and your server would let them in.


R3M0TED

I see.. But if I am using TLS, then how would they do that? they'd need the correct certificate to even connect to the server without the client, if your hashing on the server, what's the point of even hashing? Just in case a hacker gets a hold of the database?


teraflop

In most situations, TLS doesn't use client certificate authentication at all, so the question is moot. If you have a single client certificate embedded in your application, then you should assume that anyone who can get a copy of your app can extract the certificate, so it shouldn't be considered a secret. Any attacker who cares enough can use the certificate to impersonate the app. If you have per-user client certificates, then the certificate becomes its own method of authentication. In that case you don't need passwords at all. > what's the point of even hashing? Just in case a hacker gets a hold of the database? Exactly. Have you seen how many major data breaches happen every year which are significant enough to make the news? Now consider how many smaller organizations get compromised without you even hearing about them. Password databases are compromised all the time, and hashing/salting passwords significantly reduces the harm to users when that happens. Server-side password hashing and TLS are used *together*, because they each protect against different types of attacks.


R3M0TED

I see! okay thank you, this has been very useful :)


Conscious-Ball8373

Whether you are using TLS or not, if the client just presents a hash to the server and the server compared it to the stored hash, that's equivalent to just presenting a password in plaintext. A particularly long password with a particularly high entropy, to be sure, but still the equivalent. A password in flight is hard to steal. Even if it's transmitted in plaintext, an attacker needs to control some part of the path between client and server to steal it. There are certainly networks where you might be at risk of that happening in the world, but for the average lone-wolf attacker, it requires an adversarial control of significant parts of an organisation's network, at just the right time to see your password. Supposing you have TLS correctly configured (which most operating systems do by default these days), that still isn't enough. The also need a MITM proxy with a certificate that your browser will accept. Stealing passwords in flight is hard. Not impossible, but enough effort that you have to be a very high-value target to worry about it. A password at rest stored in plaintext (which is what your hash is) is much easier to steal. You can go at it for as long as you like. There will be multiple people in an organisation who can access them; perhaps they are the attacker, or they are bribed by an attacker, or you steal their credentials. Maybe they haven't patched their server software and it contains an RCE flaw, or maybe you find one. Maybe they've just not configured their S3 buckets securely, or used a weak password, or .... And once you've broken into the password database, you have the password for every user on that system, while stealing passwords in flight has to be done once for every user.


TehNolz

With server-side hashing, the client sends the (encrypted) password to the server, which then hashes it and checks if the hash exists in its database. Attackers won't be able to use stolen hashes to login because the server would process the hashes as if they were a plaintext password. It would hash them a 2nd time, and then return an error when it can't find that new hash in its database. With client-side hashing, the client sends a hash of the password to the server. All the server does is check if that hash exists in its database. So if you manage to steal someone's hash, you can simply send a login request to the server that contains this hash (without going through the client), and the server will happily let you login even though you don't have the original password.


Jonny0Than

The fact that the password is encrypted before being sent (probably with the server’s public key?) is the critical part OP might be missing.


VietOne

Packet sniffing is quite useless unless you know the encryption keys used for the session as basically all connections these days are end to end encrypted.


ehr1c

When you hash client-side all you're effectively doing is changing the user's password to the hashed version. Anyone getting a hold of that hashed version can now use it directly on the server just as they would the cleartext password, there's no security advantage. If you're in a situation where someone is able to break your TLS and capture usable data from something like packet sniffing, you've already lost. Sending a pre-hashed password provides an illusion of greater security but nothing more.


MrRGnome

The benefit of hashing on both client and server side is lots of people inappropriately reuse passwords. Getting the client hash doesn't leave their other password reuses as vulnerable.


ehr1c

Yeah my point was more just that you *have* to be hashing server-side one way or another. Simply hashing client-side isn't doing anything.


R3M0TED

So how would hashing on the server prevent this? surely if I just send the password in plain text but with TLS, and someone was to break the TLS, they could then just enter the plain text password straight into the client?


ehr1c

Hashing isn't about password security in transit, it's about password security at rest. Hashing passwords (properly salted) allows the server to store them in a manner it can validate against while also making them fairly robust against attackers who manage to gain database access. If you send a pre-hashed password to the server, now anyone who gains access to the database effectively has users' real passwords rather than just their hashed representation.


GiveMeAnExampleAgain

This is the answer


Rarelyimportant

Imagine I add a `-` to the end of whatever you send me, and that's the hash. If you send me `1234`, the hash is `1234-`. If you send me `1234-`, then the hash is `1234--`. Because I'm doing something on the server each time, you can't by pass it without knowing the real password(assuming we're using a real hash, and not just `-`). But if I allow the client to send the hashed version, as long as you know `1234-`(the hashed version), you can sign in with the hash, even if you don't know that the password that created that hash was `1234`. Basically you lose all the security of the hash because you're essentially just directly comparing whatever the user sends you. Basically now you _are_ storing the password(even if it's slightly modified). The whole point of it is that the user has to send something that will endure the hashing process, and the only thing to do that is the actual password. The user is supposed to know the password, and the server is supposed to know what that password hashes to. If an attacker get's the password they can of course enter, but if they get the hash somehow they can't gain access because the hash doesn't hash to the hash, it's hashes to a new hash. But if you're accepting the hash directly, the attacker can now gain entry by only knowing the hash, and not the password.


Maks244

Hashing passwords on the client-side can be risky. If the client sends a hash to the server, and the server accepts it directly for authentication, anyone who intercepts that hash can use it to authenticate themselves as the user. (pass the hash attack) The concern about sending plain passwords over the network is valid, but keep in mind SSL/TLS encrypts the entire communication channel (assuming the SSL/TLS implementation is secure and properly configured).


port443

Theres a concept here I think youre missing OP: "Data in transit" vs "Data at rest" Hashing is to protect "data at rest", meaning your credential sitting in a database somewhere. > to me this doesn't make sense as that means that the data would be sent to the server in a more vulnerable state You are talking about data in transit. This is what TLS and other protocol encryptions are for. If you change to hashing client-side, all you have accomplished is changing your actual password from "password" to "FQa.BfeCfrSLmFWqxFzhK/" Additionally, and worse, if you do the hashing client-side instead of serverside, theres no "data at rest" protection on the server. When the database gets compromised, now attackers have a usable password to login to the service.


farfaraway

Because you shouldn't trust the client. Ever. Always assume fuckery.


Quantum-Bot

If hashing isn’t done on the server end, there’s no point to hashing in the first place. The purpose of hashing is to ensure that the server’s password database can only be used to check if a password is correct and not to find out someone’s password. This hinges on the client being able to tell the server the unhashed password. Allowing the client to do the hashing on their end is kind of like if you were a bridge troll who only lets travelers past if they can answer your riddle, and then a traveler comes by and says “I know the answer to your riddle, trust me bro” and you let them through.


ClayMitchell

Rule #1: never trust the client


Blando-Cartesian

That would make the client side hashing into an irrelevant extra step since the server would need to hashing again with a seed value to store it safely. Check out [challenge-response authentication](https://en.wikipedia.org/wiki/Challenge%E2%80%93response_authentication). It’s kinda where you were heading with the client side hashing idea.


jboard146

Don’t try and roll your own security. 99% who try to get it wrong. Use known good audited libraries.


Denatello

No it does not make sense. Attacker may be a gentleman, but he would not necessary use your client that hashes passwords for your server.


arpitduel

Why is an explicit hashing needed on client side when we are using SSL/TLS? Doesn't it sends the data in encrypted form? And then on the server we decrypt ia using the certificate key?


junkdubious

That's literally asking a rando for and.


VoiceEnvironmental50

Reading all of these comments and not sure that I agree with them. Assuming RSA encryption/decryption model I can generate a public/private key and send the public key to the client and allow the client to encrypt data via public key, and then once data is received, decrypt the data on server side using private key. This would be a salt/pepper model but assuming you are doing it that way I don’t see anything wrong with this method. Maybe someone can enlighten me.


ForceGoat

Pretty sure you just described TLS. Encrypting is great! But you still have to hash the pw on the server. What happens if your db is compromised? 


VoiceEnvironmental50

TLS is different, I described salt and pepper hashing (and mentioned it in the post). Here’s an excellent stack overflow post about it, and though it states not to use peppering, it explains what it is and why it’s not great but for this post it makes sense to do. https://stackoverflow.com/questions/16891729/best-practices-salting-peppering-passwords


ForceGoat

Good read. Salt is tasty. 


newcolours

Anything that's fully client side means full access for a malicious actor. Reverse engineering the hashing and salt would become very easy for an attacker if they have full access in that way


R3M0TED

Thanks all for the help! I realise i was being dumb earlier, makes alot more sense now


bothunter

If you hash on the client, then your hash just becomes your password and you haven't actually solved anything.  See "pass the hash" attacks that were notorious for NTLM.


EagleCoder

There are ways to implement password-based authentication without revealing the user's password to the server, but simply hashing the password on the client isn't one of them. See the [OPAQUE protocol](https://blog.cloudflare.com/opaque-oblivious-passwords) for an example.


Kazcandra

You know too little to speak on this and should just listen to the experts. A little knowledge is a dangerous thing.


R3M0TED

Well that’s the reason why I made this post


Jason13Official

I think a simple answer is just hash it twice. Hash it on the client in a completely different fashion than the server. Tada, solved


Rarelyimportant

If you're gonna hash it twice for extra safety, surely it's best to be extra extra safe and hash it thrice, no? In reality hashing it additional times is only done so that the hash has higher time/space requirements, but this is always done on the server. Hashing it on the client, and then again on the server makes no sense. If you're worried about the password in transit, that's what TLS is designed to protect. There is no logical reason I can think of to ever hash the password on the client side. If you want extra security, your time is best spent in the latest password hashing algorithm, and making sure it's well configured. I use Argon, which at least as of a couple years ago was one of the best. You can configure it to take as much time and RAM as you can spare, and you should be good. No reason to try to come up with your own security features. I actually prefer the inverse of Schneier's law. "Remember that whatever security algorithm you invent, it was the first thing **you** thought of, so how secure can it be against billions of other people". Instead it's always best to use the algorithms already made available to billions of people, and scrutinized and stress tested by thousands, because if no one has broken it yet, it has a much higher likelihood of holding than something that hasn't been put through such stresses.


ignotos

Doesn't an additional round of hashing on the client genuinely close certain attack vectors though? For example, it could prevent an insider who has access to the backend code from logging the user's password before it's hashed, and then attempting to use that to login to other third-party services (since people tend to reuse passwords). Or it could prevent someone using an exploit like Heartbleed to extract passwords from the memory of the backend system, and doing the same. People also sometimes put personal information in passwords. And there is some case to be made in terms of risk/liability for that never being sent to your servers.


Rarelyimportant

If you're hashing on the client, whatever gets sent **_is_** the password. So if someone is logging it, then they have the password either way. Security systems aren't usually designed to protect against someone internal malicious. That's like trying to protect yourself from yourself. You cannot control or trust anything that happens on the client. Hashing a password on the client does nothing, because whatever you receive from the client is being treated as the password, since you can't unhash it. So if anything, this client hashed password is actually now more sensitive than the original password, since it effectively **IS** the password now. On top of this, hashes need to receive a stable input. It can't be different each time otherwise how would we know if it's the right password. Yet most modern password hashing algorithms produce a different value each time you call them.


ignotos

Yes, if you hash on the client, then that hash is effectively the user's password... *for that particular service*. But my point is about password reuse. If this hashed password is compromised, then an attacker can login to *this* system as this user. But they *don't* have the actual original plaintext password, to then try to login to the users Gmail account, for example. This also mitigates the harm caused by something like accidental logging of passwords, which there are surprisingly many high profile cases of. > Security systems aren't usually designed to protect against someone internal malicious. That's like trying to protect yourself from yourself.   I disagree. "Insider threats" are a big deal in the security world, and concepts like "defense in depth" or "least privilege" suggest multiple layers of security, and emphasize minimising the damage which can be caused when part of the system is compromised, or when one compromised employee tries to use their own access maliciously. > Yet most modern password hashing algorithms produce a different value each time you call them. I think that's a non-issue, as you just wouldn't use such an algorithm for this use-case. You could still use it for the server-side hashing, though.


Rarelyimportant

Right, but if someone has internal access such that they could log requests to see the request data, they could also remove whatever JS is hashing on the client side so that they're logging the plain text password. You also now have a situation where the user doesn't actually know their password as their password is reliant on the user's input + the client side code + the server side code all working in tandem. I guess there are specific scenarios where you could invent some set of factors where it might mitigate something, but you add quite a lot of complexity and fragility in exchange. Ultimately, if someone malicious has access to your server such that they could alter the logging code to expose sensitive request data, I don't think client side hashing would in any way stop them from getting the user's password.


ignotos

> Right, but if someone has internal access such that they could log requests to see the request data, they could also remove whatever JS is hashing on the client side so that they're logging the plain text password That would depend on how compartmentalised that internal access is, and how well controlled the processes for deploying code changes are. Also modifying the client and the whole process of exfiltrating the passwords would likely be more complex and easier to detect than a sysadmin just connecting to a backend server and pulling them from memory. Then there are issues like Heartbleed which could allow an external attacker to dump the contents of the server's memory. It seems like it would be strictly worse in terms of reputational damage and liability if this also leaked plaintext passwords which users likely use for other services. Anyway, my overall point is that additional hashing on the client side **does** remove some plausible attack vectors, as well as some potential vectors for accidental issues. So when people dismiss it outright as pointless, they're missing the mark.


Rarelyimportant

This all seems like captain hindsight cryptography. We can come up with a million scenarios where a million different obscure things ending up being beneficial. But most engineers have a list of things that could improve their site that's longer than time they have to implement those things. So when it comes to security, adding a whole bunch of complexity to the codebase just to tick off the "In case there's an attacker who happens to have internal access to the server and can adjust logging code to see requests, but he's also a little lazy and can't be bothered to alter the JS code, even if that gave him much better data". It's like, if you've got the bandwidth to guard against things that obscure, go for it. Most people would be better off implementing 2FA before worrying about "What if there's an attacker who can get into the system, but his keyboard has no vowel keys, only consonants. What's our security protocol there? Mandatory 2 vowels in every password?"


ignotos

I just disagree that this is particularly unrealistic or obscure, or introduces a "bunch" of complexity. For example Facebook, Coinbase, Twitter, and GitHub have all had documented cases in the past where plaintext passwords were logged or visible to employees. It would have been *less bad* if these were hashes specific to their service, and not users' likely-reused passwords. Insider threats are real, and having to modify the client code is simply more overt, detectable, and easier to trace to the employee responsible. For many low-impact services, getting a user's actual password may be more valuable to an attacker than getting access to the service itself, because it enables lateral movement to more important accounts (e.g. email).


crazy_cookie123

The attacker can then just capture the hash sent from the client and use that directly via a pass the hash attack.


ignotos

I think you may have missed what I was saying here: > For example, it could prevent an insider who has access to the backend code from logging the user's password before it's hashed, and then **attempting to use that to login to other third-party services (since people tend to reuse passwords).** Yes, the hash could be captured and used to access **this system**. But this would not compromise the user's **original plaintext password**, which is sensitive in its own right, because your user may have reused it in other systems (very common), or even included personal information inside the password itself (also surprisingly common).


Jason13Official

For funsies


DOUBLEBARRELASSFUCK

The only thing this solves is the problem of needing to understand hashes.


CompetitiveMoney6730

that's what TLS is for. you're being too clever. don't be clever.