Stop passing plain passwords over the wire
this is already solved by https Stop passing plain passwords over the wire
this is already solved by httpsWell, the most common such protocol is TOTP, which still requires the server to store your full password. In that sense it's worse than a naive password exchange, which only requires the server to store your hashed password.
There are other password protocols that require neither transmission nor server retention of the full password, but it seems worth noting that the protocol we actually have didn't bother with that.
I'm not sure what you want to ask.
And with digest auth, the server must have the plain text password already. But sure, maybe there is a third option.
The problem with TLS client certs, of course, is the fact you need a method of signing CSR's, and the terrible UX modern browsers have for client auth, especially on mobile.
Your suggestion is basically going back to the days where databases stored plaintext passwords in the database, just that the plaintext happens to be a hash.
Shouldn’t it be a proper challenge/response? Otherwise the hash is barely better than the password.
So, an attempt to solve your question eventually leads to using an asymetric PAKE. But, this is way, way more complex. You'd really have to squint your eyes to believe that the diminishing returns are worth it.
If you just hash the password, the hash becomes the password. You're not solving the problem that way, you're just switching around definitions.
There is an alternative that's supported in most platforms, and that's WebAuthn. Not even a need for a password automatic secure handshakes and with the right protocols, the keys differ per site so they're very hard to spoof through phishing. You can achieve much of the same thing with client TLS certificates, but the UX for that is even worse than the UX for HTTP Basic.
To that one site. But users reuse passwords and if a criminal only has a hash they can't reuse it across sites.
It's not that I don't understand where you're coming from (I once almost started writing such a library a few years back!), but I just can't think of a threat model where this makes sense. That's also what moved me away from working on such a system.
To me, this approach feels like an attempt to recreate software-only U2F, but outside the browser. I don't think client side code can fix these problems. It can make stealing passwords more difficult for criminals if every website uses their own bespoke password processing script, but that'll also add a huge attack surface to your code and it'll be a burden to maintain.
A) Controls the code running the auth API
B) Controls the javascript
As if that's the common attack.
The common attack is that the attacker has a read on the hash, either through injection vulnerabilities or other leaks.
Your attacker, as described, has remote code execution on a server that hosts the auth API and the Javascript in one place. That is a very specific, powerful attacker!
> but I just can't think of a threat model where this makes sense
1. An attacker has CSRF and can trick your code into sending the hash to them. This significantly reduces the harm of that attack.
2. An attacker has an injection vulnerability giving them read access to hashes ie: sql injection, perhaps the most significant and relevant attack to discuss with passwords.
3. An attacker takes advantage of a timing attack, bruteforcing the server and measuring response times to leak its value. They can now only leak the hashed value, which is going to take way longer to leak and doesn't expose their password.
And more!
This defense tackles what are very very arguably the major threats to consider with regards to password security (they're the big ones in OWASP top 10).
> It can make stealing passwords more difficult for criminals if every website uses their own bespoke password processing script, but that'll also add a huge attack surface to your code and it'll be a burden to maintain.
You can significantly reduce harm and attack surface with all of 3 lines in your frontend code.
salt = hash(username + static_salt)
password_hash = pbkdf2(plaintext_password, salt)
it's trivial to implement this.I'll grant you that PAKEs may be more complex to implement today, but even if we talk about a very basic implementation of client side hashing I think there's obvious value.
If you presume the attacker can only read the data transmitted but cannot alter it, your system might work, but I'm not sure in what scenario a hacker can break HTTPS secrecy without also being able to modify the contents of traffic over the wire.
A CSRF vulnerability won't let you send the password to a random host, unless you have full arbitrary code execution (in which case your protections don't make sense either) or if your auth code is unrealistically buggy (letting the attacker embed secrets in a resource somehow).
The database already contains hashes for normal password auth, so I'm not sure why your system would be any better. The password database isn't stored client side, after all, and I hope nobody is still storing passwords in plaintext.
I'm not sure why an attacker would be able to guess the hash from a timing attack, if they can do that then the hashing implementation is very flawed, to the point you just shouldn't be hashing passwords with it.
Your custom salt/hashing system solves password reuse I suppose, but it doesn't add any protections to your website while adding complexity at your cost. For your website, you just changed the way the password looks (which is the hash, not the direct input) at the cost of needing Javascript execution.
In my opinion, your login page would be a lot more secure with a CSP that disallows all scripting, just in case, and uses a simple system that's easy to spot mistakes in, like HTTPS POST or Basic auth.
I don't think that attacker is worth dealing with. At that point you're outside of the security responsibilities of a website and it's the operating systems job to provide security.
> But, breaking basic passwords sent over a secure channel aren't a common attack in general.
Isn't it? Lots of passwords are sent over TLS but SQL injection is still a top 10 vulnerability.
> a hacker can break HTTPS secrecy without also being able to modify the contents of traffic over the wire.
I'm not implying that they can. I'm implying they can read the hashed values after being transmitted to the server.
So attacker in the following positions, at least: 1. Owns your auth endpoint (but not your CDN)
2. Owns your proxy
3. Has read access to your logs and the password is in those logs
4. Has a SQL injection or timing attack against your password auth/ db
> A CSRF vulnerability won't let you send the password to a random host, unless you have full arbitrary code execution
Yeah true, I was thinking about the auth token, not the password.
> I'm not sure why an attacker would be able to guess the hash from a timing attack, if they can do that then the hashing implementation is very flawed,
Timing attacks aren't a property of the hash but of the operations on that hash.
> The database already contains hashes for normal password auth, so I'm not sure why your system would be any better.
Do you mean that the database would be doing server side hashing regardless? That's true (I sure hope). But the attacker will have to brute force a much larger space to recover the plaintext password and the point of doing the client side hashing is to protect other sites if a user reuses their password on those sites.
> Your custom salt/hashing system solves password reuse I suppose
To be clear, that's the point, and I don't think that's small. It's about reducing harm to your users - even if within the scope of your website your user is still vulnerable you are protecting them within the scope of other websites.
I haven't made this argument yet, but I believe it also adds security elsewhere by distributing the cost of your hashing to clients. Your server has to handle N clients, and maybe needs to response in 5ms to each client - so it can spend, say, 3ms on hashing. To keep your tail latencies down you might try to do 1ms of hashing.
But you don't have to worry about your compute if you push it to the client. You can have the client perform, say, 1M rounds of PBKDF2.
So the attacker has two choices.
1. Brute force the client hash, which is 32bytes and really not feasible. That is to say that in a naive brute force they start with 32bytes 0'd out and start counting until they reach your hash - not fun.
2. Brute force the client password, which has a huge number of rounds that you could never get away with on your server. 1M rounds of pbkdf2 is not something you'd want to do on your server but distributed across your clients it's no problem at all - a few hundred milliseconds perhaps. But that's devastating to an attacker trying to recover the plaintext - of course, with some caveats (a relatively weak salt).
I haven't put enough thought into this benefit to claim it, but I may as well throw it out there.
> but it doesn't add any protections to your website while adding complexity at your cost.
It's very little complexity at very little cost. It's a few lines of code that execute at the edge - you pay nothing for those cycles.
> at the cost of needing Javascript execution.
I don't consider this a cost. I think it's totally ridiculous to say that JS execution as a requirement is a "cost" - the vast majority of websites require JS, and there are plenty of good reasons for it (like telling your user their password is too short). If you care so much about JS as a cost, ok, don't do client side hashing.
> In my opinion, your login page would be a lot more secure with a CSP that disallows all scripting, just in case, and uses a simple system that's easy to spot mistakes in, like HTTPS POST or Basic auth.
I disagree. A CSP would be an excellent thing to implement, and everyone should do so. But I don't think that completely denying script execution is a good idea - your users are far more vulnerable to using weak and/or reused passwords than XSS on a site with the minimal scripting necessary to implement this code (no 3rd party packages are required for the code I mentioned).