Hacker News new | ask | show | jobs
by tbrowbdidnso 3401 days ago
The author is mistaken about the side channel existing. In the most common case of login and token generation it just doesn't.

With logins you compare the hashed password to a stored hash. The author mentions that you can tell how much of the hashes match because the compare function exits early if they do. This might be true, but it doesn't give you anything.

When using a secure hash function with a salt, the attacker being able to guess how much of the two hashes match gives him no information because:

1) he doesn't know what hash is stored 2) he doesn't know what his password attempt hashed to 3) he doesn't know the salt

The only thing that the attacker knows is that he created a hash with his attempt that matches the first few bytes of the real hash. If you use a strong hashing algorithm this is useless information and will happen at random.

2 comments

That's not how I read it at all. The author is saying that non-password tokens can be vulnerable if you don't treat them the same way you'd treat passwords and is essentially suggesting that they be split into username-like and password-like fields.

There's another unrelated solution to the problem: make the tokens be AEAD [1] output from a scheme with a global (perhaps rotated) secret or signed output from an asymmetric cryptosystem. Then you're protected by the usual AEAD or digital signature guarantees as long as you properly verify the token before doing something silly like looking up the ciphertext in a database.

[1] Strictly speaking, encryption may be unnecessary depending on what's in the token.

If you want to avoid timing attacks on the username and pw isn't the easiest way to just hash them as if they're both passwords? (at least on initial login). Since the hashes are cryptographically secure you can't infer any timing information from incorrect guesses
We aren't interested in timing attacks on username+password, we're interested in timing attacks on authentication schemes that only involve one string (i.e. ONLY a token).

Simply hashing it before a lookup may be sufficient.

However, it's actually easier to reason about separating the search operating (which leaks timing information unavoidably) from the validation operation (which shouldn't leak timing information if we can avoid it) than relying on a hash function to blind the operation completely.

Can you explain in what way is it easier to reason about separating the search operation from the validation operation?

I can argue that it is easier to reason about simply hashing and then looking up because once hashed, the lookup does not leak any timing information, whereas in your solution the lookup does leak timing information.

Can you refute my argument?

Hashing is deterministic.

If you give the system m, you can probably deduce H(m). If you can send candidates m, m', m'', etc. and compare the timing information of H(m), H(m'), H(m''), etc. you can learn some information about the hash being stored.

This still probably isn't exploitable (you'd need a practical preimage attack, at a minimum), but you're still leaking some knowledge from the timing leak of the comparison of the candidate hash with the stored hash.

With a split token approach, the verifier is totally unknown to the attacker. You can generate a valid selector from observing timing observations... and that's it. Game over. Find another way in the system.

If you have a 128-bit random string as your inputs, this will probably never be guessed.

It's easier to reason about the security consequences of no leak versus a minor, probably impractical leak.

You can mix the hash with a salt that the attacker doesn't and cannot ever know. This is pretty standard and prevents the leak of timing from revealing anything about the hash. The only time this fails is if your hash function is broken, and if that's the case you've got much bigger problems
> The author mentions that you can tell how much of the hashes match because the compare function exits early if they do. This might be true, but it doesn't give you anything.

I think you may be confused. The article discussed two cases initially:

1. Username and password hash.

2. Naked string used in a SELECT query.

The latter case is where the timing leak can occur. That password_verify() is constant-time is just a nice-to-know defense-in-depth feature, not a must-have.

(Disclaimer: I am the author.)