2

I'm implementing custom authentication & session management system in Node.js & PostgreSQL. My goal is to implement sessions that expire after 2 weeks (if not refreshed/renewed).

OWASP and other resources suggest to store unhashed session IDs both in database and cookie. However, if those session IDs are leaked from the database, then they can be used to successfully authenticate before they expire.

I wonder if hashing sessions would add some additional security against such situations. The implementation I'm thinking about would work like this:

  1. User authenticates.
  2. A session is saved to database with id (UUID v4) and token_hash (SHA256 hash of cryptographically secure random string).
  3. Both id and original unhashed token are saved to response session cookie(s).

Then on subsequent requests:

  1. Server reads id and token from request session cookies.
  2. If there's a session found with id, then the token is verified against token_hash. If it succeeds, then the user is authenticated.

(I'm thinking about using both session id and token/token_hash because I think it will be faster to first find the session simply using id, and only then verify token against token_hash. Otherwise, the token would need to be hashed on every request to find the session, which, I assume, would be slower, even if some fast hashing function like BLAKE3 would be used.)

  • I think this is actually a duplicate of https://security.stackexchange.com/questions/138389/should-i-also-hash-my-session-id-before-storing-it-in-the-database, which is in turn a duplicate of https://security.stackexchange.com/questions/136122/how-to-secure-store-sessions-values-in-webapps . Accepted answer is "Yes", second answer is "No, if you implement some advanced logic that makes it not necessary". – Alex Sep 27 '21 at 06:55
  • @Alex, these questions are indeed close, but my question is about specific implementation not mentioned in them. – Dominik Serafin Sep 27 '21 at 12:55
  • Why design a custom implementation when many proven and vetted methods (and library implementations) exist? – multithr3at3d Oct 02 '21 at 01:01
  • 1
    @multithr3at3d there can be many reasons, e.g. 1) greater control over implementation 2) needs not supported by existing solutions 3) actually creating/maintaining those 3rd party solutions 4) learning 5) curiosity – Dominik Serafin Oct 03 '21 at 03:02
  • If your database leaks, you have bigger problems than someone using the tokens. – ThoriumBR Oct 27 '21 at 20:56
  • @ThoriumBR with that attitude, why even hash the passwords then? – Dominik Serafin Oct 28 '21 at 18:47
  • @DominikSerafin sessions are transient, passwords aren't. Sessions are random, passwords usually aren't. Sessions aren't reused, passwords are. You can revoke all sessions and your users can log back in. You cannot do the same with passwords. If you hash the passwords, the database leak will take a while to crack all passwords, unless you use plain MD5. – ThoriumBR Oct 28 '21 at 22:24
  • And I believe "learning and curiosity" are the only valid reasons for implementing a session management from scratch... – ThoriumBR Oct 28 '21 at 22:25
  • @ThoriumBR of course, hashed passwords should take priority over hashed sessions. However, my point was that if passwords were unhashed, I'd still have bigger problems than that if my database leaks. You can always reset your user passwords, just as you can revoke sessions. ​So, following your logic, if I'll have bigger problems anyway, why should I even hash passwords? ― Password hashing is defense in depth, just as session hashing. The goal here is to minimize damage. – Dominik Serafin Oct 29 '21 at 12:32
  • 1
    I think you don't realize that hashing sessions have a performance cost that is paid on every request that uses the session token. A hashed password pays the cost only during login. – ThoriumBR Oct 29 '21 at 13:55
  • @ThoriumBR If you read my question again (especially the last line) you will see that the idea behind this specific implementation was with performance in mind. So, why do you think I don't realize about performance costs? Anyway, 1-2ms longer requests from SHA256 validation are a fine trade-off for me if it means enhanced security. – Dominik Serafin Nov 02 '21 at 20:35
  • It does not mean enhanced security at all. A random token is indistinguishable from an encrypted or hashed token. It can protect against a database leak, but on case of such event the damage is so high that protecting the tokens is futile. – ThoriumBR Nov 03 '21 at 01:19
  • @ThoriumBR if it adds a layer of protection after a database leak, then how is it not enhanced security? – Dominik Serafin Nov 03 '21 at 10:24
  • "It prevents your computer battery from exploding if a devastating fire consumes the entire building". It adds a layer of protection if a catastrophic event occurred, when that protection does not mean anything anymore. – ThoriumBR Nov 03 '21 at 10:51
  • @ThoriumBR then again, if database leak is be-all and end-all like you say, why even hash the passwords then? Hashing passwords doesn't protect from database leak as well, it's a layer of protection that is relevant only after the "catastrophic event occurred". – Dominik Serafin Nov 03 '21 at 11:16
  • the reason to save only the hashed password is because some users re-use logins. So if the database is leaked, you might compromise other accounts. (it also helps protect the actual password if you were using that as the "remember me" type cookie or session) Session tokens are nice because they can be revoked/changed without the user having to change their password. But a session is not really authentication and shouldn't be relied upon for sensitive actions (such as changing e-mail/password, making purchases, etc... require a relogin in those cases) – pcalkins Feb 24 '22 at 21:20
  • 3
    DB leaks are frequently read-only (lots of SQLi is limited this way, as are exposed backups or clone functions, etc.). If I gain R/O access to the SE DB and it's using hashed session tokens (or JWTs or similar), I can read everything that has been written - even if it's not visible to most users anymore - but that's it. Bad but hardly catastrophic for the users; most content on SE is public anyhow, especially to privileged users. If I gain R/O access to the DB and it's got unhashed session tokens in it, *I can hijack your session and post content under your name*. – CBHacking Feb 25 '22 at 11:53

1 Answers1

0

I think it will time consuming since you will validate id and token on each request. In my opinion, what you could do is implement stateless JWT authorization. Implement custom claims w.r.t to user ID in JWT token and set expiration time while generating the JWT token. It will minimize compute time of auth validation.

  • 1
    In terms of *compute* time, JWTs are almost strictly worse than server-stored random session tokens, even if the random tokens are hashed. JWT signature validation requires a minimum of two rounds of hashing (HMAC), or much much worse if asymmetric signatures are used. What JWTs avoid is the time to hit the DB or other storage. – CBHacking Feb 25 '22 at 11:44