Take the 2-minute tour ×
Information Security Stack Exchange is a question and answer site for Information security professionals. It's 100% free, no registration required.

I am developing an application which has a client-server relationship, and I am having trouble deciding on the algorithm by which the session identifier is determined. My goal is to restrict imposters from acquiring other users' private data.


I'm considering two options:

Option 1: Generate a random 32-character hex string, store it in a database, and pass it from the server to the client upon successful client login. The client then stores this identifier and uses it in any future request to the server, which would cross-check it with the stored identifier.

Option 2: Create a hash from a combination of the session's start time and the client's login username and/or hashed password and use it for all future requests to the server. The session hash would be stored in a database upon the first request, and cross-checked for any future request from the client.

Other info: Multiple clients can be connected from the same IP simultaneously, and no two clients should have the same session identifier.


Question: Which of these options is a better approach, with regards to my concerns (below) about each?

My concern over the first option is that the identifier is completely random and therefore could be replicated by chance (although it's a 1 in a 3.4 * 1038 chance), and used to "steal" one user's (who would also need to be using the client at the time) private data.

My concern over the second option is that it has a security flaw, namely that if a user's hashed password is intercepted somehow, the entire session hash could be duped and the user's private data could be stolen.

Thanks for any and all input.

share|improve this question
1  
Many proposed session handlers are posted to security.se. I suggest doing some research into this topic before coming up with your own system. –  Rook Dec 2 '12 at 21:01
    
Most of the proposed session handlers I've seen are all website-browser relationships, which aren't entirely applicable to a client-server relationship. Is there a more concise tag I should be searching by? –  Vulcan Dec 2 '12 at 21:22
1  
In the generic sense there is no difference. You still can't trust the client, and many of the same attack patterns still exist. –  Rook Dec 2 '12 at 22:22
add comment

3 Answers

up vote 10 down vote accepted

The basic concept of a session identifier is that it is a short-lived secret name for the session, a dynamic relationship which is under the control of the server (i.e. under the control of your code). It is up to you to decide when sessions starts and stop. The two security characteristics of a successful session identifier generation algorithm are:

  1. No two distinct sessions shall have the same identifier, with overwhelming probability.
  2. It should not be computationally feasible to "hit" a session identifier when trying random ones, with non-negligible probability.

These two properties are achieved with a random session ID of at least, say, 16 bytes (32 characters with hexadecimal representation), provided that the generator is a cryptographically strong PRNG (/dev/urandom on Unix-like systems, CryptGenRandom() on Windows/Win32, RNGCryptoServiceProvider on .NET...). Since you also store the session ID in a database server side, you could check for duplicates, and indeed your database will probably do it for you (you will want this ID to be an index key), but that's still time wasted because the probability is very low. Consider that every time you get out of your house, you are betting on the idea that you will not get struck by lightning. Getting killed by lightning has probability about 3*10-10 per day (really). That's a life threatening risk, your own life, to be precise. And yet you dismiss that risk, without ever thinking about it. What sense does it make, then, to worry about session ID collisions which are millions of times less probable, and would not kill anybody if they occurred ?

There is little point in throwing an extra hash function in the thing. Properly applied randomness will already give you all the uniqueness you need. Added complexity can only result in added weaknesses.

Cryptographic functions are relevant in a scenario where you not only want to have session, but you also want to avoid any server-based storage cost; say, you have no database on the server. This kind of state offloading requires a MAC and possibly encryption (see this answer for some details).

share|improve this answer
add comment

Session IDs need to be cryptographic strength random, and unique. If an attacker can guess a legitimate session ID, he may impersonate that user.

Option 1 is your best bet, as long as you use a proper CSPRNG, and not something like rand() from a standard library. Using something like option 2 isn't as safe, since usernames and times are easily guessed or brute-forced.

Take a look at how PHP's session ID generator code works, and you'll see that a hash function is used to combine the IP address of the client, the current time (seconds and microseconds) and some values from PHP's Linear Congruence Generator (LGC) RNG as a baseline. If an OS-specific random source is available, further entropy is mixed into the ID from that function. This gives a reasonable security margin if no strong entropy source is available, but provides strong security if one is.

share|improve this answer
    
Thanks, I'll be going with option 1 then. If I could mark two answers as accepted, I would, but I feel like Thomas's answer better addressed my concerns. Great answer regardless; +1. –  Vulcan Dec 2 '12 at 23:33
    
Glad it was helpful. I agree that Thomas gave a better answer, too. There's a reason he's known as our resident cryptographer! –  Polynomial Dec 2 '12 at 23:41
    
I would point out that PHPs built in session generator isn't all that great, at least not until the RNG is replaced by a cryptographically secure one. –  ewanm89 Dec 3 '12 at 0:56
    
@ewanm89 Thanks for the point out; I'm already using Java's CSPRNG (SecureRandom) for my 128-bit unique session identifiers. –  Vulcan Dec 3 '12 at 1:35
    
@ewanm89 If you read through the code, you'll see that it is cryptographically secure. The baseline is a weak combination of an LCG and various time / IP values, but if an OS-specific CSPRNG is available (e.g. /dev/urandom or Microsoft's CAPI RNG) it uses that. You'd have to be on a pretty unusual / exotic setup for an OS-specific CSPRNG to not be available. –  Polynomial Dec 3 '12 at 9:40
add comment

Session Identifiers should be signed then you don't have to worry about people trying to guess the session id.

Also check for collisions to make sure you haven't given away that identifier already.

share|improve this answer
2  
Signing doesn't protect the privacy of the value. It only attests that the value came from the server. You need to actually perform a key exchange and encrypt the session key in transit to prevent it being able to be captured. The only exception to this would be if the client has a trusted certificate in which case they could sign any challenge to verify their identity to the server. –  AJ Henderson Apr 18 '13 at 13:13
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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