0

I am writing a service-oriented (REST) application that is (nearly) totally stateless: it can authenticate by API keys, but for web UI it uses the session where it stores nothing but an authenticated user's ID (int). Session ID is generated randomly as it's usual to see, user ID's are never exposed to the users as users are always referenced by their username

Here's the idea I got. What if instead of assigning random session ID I would generate it in the following fashion:

N1 random bytes not including flag byte + flag byte + user ID + flag byte + N2 random bytes;

or in other words, N random bytes containing a scannable ID somewhere within, all encrypted with server's secret key. It's also possible to use client's IP as a part of the string or as IV, to mitigate session hijacking.

The benefit of this approach is that the need of session is completely eliminated, and for scalability matters it's only required that all nodes use the same secret key (session replication is not required either). With regard to performance I'm not sure whether in-memory decryption (let's say, 128-bit AES) would be faster or slower than reading session data from disk and pruning it time to time. The only attack vector I can think of is attacker creating two accounts in a row (so that ID's are sequential) and bruteforcing their two session ID's to obtain the secret key (which, I believe, would not be feasible if it is effectively long).

What I want to ask is:

  • What do you think about security of such approach? (I'm concerned since the only recommendations I have seen so far is "use strong random for session ID's", and never read about such encrypted session ID approach — but that might be just people really loving to use session to store data there);
  • What are the possible ways of cryptoanalysis beyond the described one?
  • What are the downsides, beyond possibly long session ID?
  • Is it a known approach (then where is it documented?)
0

Encryption is the wrong tool, because you need to prevent users from changing the session data, not from reading it. The user ID is not a secret, but it would be a disaster if people could just change it to anything they want.

In other words, you must enforce the integrity and authenticity of the session data. Encryption generally cannot do this. What you want is an HMAC, and frameworks like Ruby on Rails indeed take this approach.

However, an HMAC is much harder to get right than a simple random ID, and client-side sessions have a couple of inherent problems. For example, if your session key is leaked, anybody can forge any session. You also can't just terminate a session. And last but not least, client-side sessions are vulnerable to replay attacks, that is, the user can revert the changes you make to the session data simply by using the old cookie.

  • Well, if the data is encrypted, it is nearly impossible to change it without knowing a key, isn't it? Impossible to terminate — good point. Weird that I didn't think of it. With regard to replay — yeah, good point too. Even though it's only the ID I store, that's still the thing. In cryptographic CSRF tokens they mix timestamps into values to check for staleness – Actine May 18 '14 at 20:01
  • In fact, I'm burying the idea this instant. Inability to terminate the session is a killer flaw. I guess, if I ever plan to scale out and drop the session completely, I'll just have my client-side code send basic auth header with user's credentials in every request (https, of course). – Actine May 18 '14 at 20:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.