Skip to content

Instantly share code, notes, and snippets.

@paragonie-scott
Last active September 22, 2016 20:18
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save paragonie-scott/d5fa1d432acc0342ba7c88686b0c9236 to your computer and use it in GitHub Desktop.
Save paragonie-scott/d5fa1d432acc0342ba7c88686b0c9236 to your computer and use it in GitHub Desktop.

Via Twitter

Authors consider SQLi as main attack vector. Hashed token mitigate r/o SQLi, encrypted mitigate r/w SQLi

That actually doesn't buy you anything. Consider the following table schema:

CREATE TABLE reset_tokens (
    tokenid BIGSERIAL PRIMARY KEY,
    selector TEXT,
    verifier TEXT,
    user BIGINT REFERENCES users (userid),
    expires TIMESTAMP
);

We recommended hashing the verifier. You might think encryption would mitigate against read/write SQLi, but you can do this:

  1. Issue a reset for an unprivileged user.
  2. UPDATE reset_tokens SET user = {$target} WHERE selector = {$knownToAttacker}
  3. Access the URL.

That works even if you can't just break out of the database, into the filesystem, and exfiltrate their encryption keys.

@adedov
Copy link

adedov commented Sep 21, 2016

UPDATE reset_tokens SET user = {$target} WHERE selector = {$knownToAttacker}

It depends on content of the token. Storing encrypted JWT with proper "sub" and "exp" may solve vector identified above. In fact, JWT is a standard way to represent authentication information, why not also use it as "password reset" authenticator?

@paragonie-scott
Copy link
Author

Why not just specify HMAC-SHA256(message=userid, key=verifier) instead of SHA256(verifier)? Then we can avoid the headache that is JWT. :)

@adedov
Copy link

adedov commented Sep 21, 2016

@paragonie-scott, hm. It seems you are right. "brevity is the soul of wit" :)

@paragonie-scott
Copy link
Author

paragonie-scott commented Sep 21, 2016

Out of curiosity: Why JWT specifically? What does JWT offer that you can't solve with hash_hmac() and hash_equals()?

store the same token wrapped with encryption

I don't really see a need for encryption. All you need is, given a threat model of UPDATE queries, message integrity. That's what HMAC offers.

This scheme seems to mitigate most of confidentiality and integrity threats with good crypto that is under developer control.

What's "good crypto" about JWT that isn't offered by HMAC?

@adedov
Copy link

adedov commented Sep 21, 2016

@paragonie-scott, may be not: verifier is know to attacker. so he can produce HMAC(message=victim-user-id, key=attacker-verifier), right?

@adedov
Copy link

adedov commented Sep 21, 2016

@paragonie-scott, by good crypto I meant something opposed to splitting verifier.

IMHO we can rely on HMAC if key is secret and not known to attacker. E.g. storing something like HMAC(message={userid, verifier}, key=system-secret).

@paragonie-scott
Copy link
Author

Yes, that's a good point. :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment