> The attacker I describe has MITM access. The attacker can read and modify page contents, but nothing on the server side. This can only be achieved by malware on the client side or tomfoolery with certificates, so it's not a common attack for sure. But, breaking basic passwords sent over a secure channel aren't a common attack in general.

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).