length of a session ID ...

Discussions of secure PHP coding. Security in software is important, so don't be afraid to ask. And when answering: be anal. Nitpick. No security vulnerability is too small.

Moderator: General Moderators

Post Reply
User avatar
pavanpuligandla
Forum Contributor
Posts: 130
Joined: Thu Feb 07, 2008 8:25 am
Location: Hyderabad, India

length of a session ID ...

Post by pavanpuligandla »

Hii..
can anyone provide information about the length of PHPSESSID?
i saw JSESSID is of 16 characters length and in my application PHPSESSID is of 26 characters,
but in gmail, i saw SID of above 100 characters..

does this session ID length has any prominence?
please post detailed session ID information like,
how many characters can a PHPSESSID contain?
are there any security vulnerabilities if sessid is small?

Many Thanks,
Pavan.P
jmut
Forum Regular
Posts: 945
Joined: Tue Jul 05, 2005 3:54 am
Location: Sofia, Bulgaria
Contact:

Re: length of a session ID ...

Post by jmut »

As long as it is unique it doesn't matter. I'd say the longer sid the bigger chance of it being unique. Well of course should be somehow hard to guess :)
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Re: length of a session ID ...

Post by Mordred »

The purpose of SIDs is to be - as jmut already said - unique and unguessable. This is generally achieved by taking a sufficiently strong random string, the length does not matter, as long as it doesn't truncate the entropy of the random. An example:

Here is a 32 character random hexadecimal string:

Code: Select all

$s = md5(mt_rand(128)); //32 characters
Here is a 8 character random hexadecimal string:

Code: Select all

$s = '';
$sChars = '0123456789ABCDEF';
for ($i=0;$i<8; ++$i) $s[$i] = $sChars[ mt_rand(16) ]; //8 characters
Which one is better (i.e. harder to guess)? The longer or the "more random" one? Let's see:

Assuming that mt_rand() is a perfect random (which it isn't but that's another matter), the first SID has an entropy of 7 bits (128 = 2^7), while the second one has 32 bits (16^8 = 2^32). In other words, one would expect to guess the first SID in 64 attempts on average (or a bit more than 8 attempts if we don't care whose SID we're stealing), while for the second case it's 2^31 attempts for a certain SID and 2^16 attemps for a random SID.

Note that these are artificial examples so we can compare their entropy. None of them is suitable for practical usage!

Here's one for homework: How strong is this random SID (again assuming that rand and md5 do not lose entropy):

Code: Select all

$s = '';
$sChars = '0123456789ABCDEF';
for ($i=0;$i<1024; ++$i) $s[$i] = $sChars[ mt_rand(16) ];
$s =md5($s);
 

The best way to deal with SIDs in PHP is not to deal with them at all - the internal method for generating them will be better than anything one can cook at home. It uses strong random values (with enough entropy) and long enough SID strings.

I see no point in having SIDs as long as 100 characters. My guess would be that gmail stores some actual information (apart from the random component) in there.

Edit: added some bolding to a paragraph above.
Last edited by Mordred on Mon Sep 29, 2008 9:18 am, edited 1 time in total.
User avatar
pavanpuligandla
Forum Contributor
Posts: 130
Joined: Thu Feb 07, 2008 8:25 am
Location: Hyderabad, India

Re: length of a session ID ...

Post by pavanpuligandla »

Thanks alot mordred.. i'm using mt_rand() function now to generate random session id's.
i understood the concept..
Many Thanks,
Pavan.P.
User avatar
Mordred
DevNet Resident
Posts: 1579
Joined: Sun Sep 03, 2006 5:19 am
Location: Sofia, Bulgaria

Re: length of a session ID ...

Post by Mordred »

pavanpuligandla wrote:Thanks alot mordred.. i'm using mt_rand() function now to generate random session id's.
i understood the concept..
Mordred wrote:The best way to deal with SIDs in PHP is not to deal with them at all - the internal method for generating them will be better than anything one can cook at home. It uses strong random values (with enough entropy) and long enough SID strings.
André D
Forum Commoner
Posts: 55
Joined: Thu Aug 28, 2008 7:03 pm

Re: length of a session ID ...

Post by André D »

Sorry to resurrect an old thread, but I think it's good to be knowledgeable of how PHP's session IDs really work, and why they look the way they do.

As has already been stated, session IDs must be unique and unguessable.
Mordred wrote:The best way to deal with SIDs in PHP is not to deal with them at all - the internal method for generating them will be better than anything one can cook at home. It uses strong random values (with enough entropy) and long enough SID strings.
I agree with Mordred, don't try to contrive your own method for generating session IDs.

I'm not sure how much entropy PHP uses for session IDs by default, but on Linux you can increase the entropy with these php.ini settings:

Code: Select all

session.entropy_file = /dev/urandom
session.entropy_length = 128
Note that session.entropy_length is in bytes, and you can set it higher if you want. Another thread discusses sufficiently-random numbers.

The original question was regarding the length of session IDs generated by PHP. The length is affected by the php.ini settings session.hash_function and session.hash_bits_per_character. For session.hash_function, 0 means MD5 (128 bits) and 1 means SHA-1 (160 bits). (Note that PHP 6 opens session.hash_function up to many more hash algorithms.)

The session.hash_bits_per_character setting lets you pick the notation that is used for displaying these 128 or 160-bit hash digests. It can be between 4 and 6; 4 means hexadecimal (2^4 = 16), 5 means base-32 (2^5 = 32) and 6 means base-64 (2^6 = 64). (Note that these base-32 and base-64 notations are not exactly the same as the standardized Base32 and Base64 encoding schemes.)

If you specify SHA-1 and 5 bits per character, your session IDs will be 32 characters long because 160 / 5 = 32.

In some cases there are fewer bits left at the end than bits per character, so the last character of the session ID will have a smaller base than the others characters. For example, using MD5 with 5 bits per character yields a 26 character session ID. The first 25 characters can be any one of the base-32 characters, but the final character will be in the range 0-7. This is because 128 / 5 = 25.6. 128 % 5 leaves only 3 bits for the final session ID character, and 2^3 = 8.

The same thing happens when using MD5 with 6 bits per character (the last session ID character will be in the range 0-3) or SHA-1 with 6 bits per character (the last session ID character will be in the hexadecimal range 0-F).

Code: Select all

                  4 bits/char    5 bits/char    6 bits/char
128-bit digest    32 char SID    26 char SID    22 char SID
160-bit digest    40 char SID    32 char SID    27 char SID
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: length of a session ID ...

Post by kaisellgren »

By default PHP's session system is very insecure.

First of all, the session identifier PHP generates is not very secure, but should serve its purpose in basic websites. For more paranoid and security important applications, it is a must to have stronger SESSID's. You can customize the behavior of this like already stated in the previous post.

By default, the session identifier is something like this:

Code: Select all

$_SERVER['REMOTE_ADDR'].time().microtime().((float) mt_rand()/(float) mt_getrandmax())*10
The IP address is very potentially known by the attacker and so is the time (e.g. leaked in HTTP) and the microtime is a small factor. The only piece of information that makes it usable is the use of linear congruential generator.

Often when people create own session identifiers in own session systems, they might use something like uniqid() for that. That is not very secure. It's almost the same as the built-in session identifier. uniqid() is similar to this:

Code: Select all

sprintf("%s%08x%05x%.8F",'',$sec,(($usec * 1000000) % 0x100000),((float) mt_rand()/(float) mt_getrandmax())*10)
At this point you might think that I'm harsh and just throwing thoughts from my head, but believe in me. I know this stuff, I've coded several C++ and Assembly random generators and analyzed how this kind of stuff works. And if you do not believe in my sayings, test yourself by running this code:

Code: Select all

list($usec, $sec) = explode(' ',microtime());
echo sprintf("%s%08x%05x",'prefix',$sec,(($usec * 1000000) % 0x100000)),'<br>',uniqid('prefix',false);
You will see something similar to this:
prefix499ca49c6a924
prefix499ca49c6a948
First it ouputs "my own PHP uniqid()", then the PHP's internal uniqid(). The last 2 characters are different, because the microsecond has moved forward because the execution of those functions does not happen so fast.

The fact is, whether you use PHP's session system or not, you are often vulnerable to many attacks. For instance, the session storage attacks are very possible in most implementations. There are several things to remember and implementing your own session system is harder than you might think at first; you have to create strong session identifiers, prevent fixations, many kind of hijacking attempts, poisoning attacks, storage attacks, transactional processing must be taken care of, and last, but not least, you have to prevent race conditions and any other potential issues that raised, because of lots of new code you just created.

Even if you use stronger session identifiers and protect from hijacking and fixation, you are still in risk. Also, many applications tend to move their session system into the database. Is that a good approach? That depends entirely how educated the coder was/is.
André D
Forum Commoner
Posts: 55
Joined: Thu Aug 28, 2008 7:03 pm

Re: length of a session ID ...

Post by André D »

This might be a good place for me to inject a shameless plug for my FixedBitNotation class, which I posted in the Coding Critique forum but no one commented on. :) If you're generating your own random strings using one of the strong techniques Kai talks about all the time, you can use FixedBitNotation to represent it in a customized notation that suits your needs. Whether you're creating unique tokens for use as session IDs, anti-CSRF form IDs, or anything else, I often see people using hexadecimal. Hexadecimal tokens are longer than base-32 or base-64 derived tokens. With FixedBitNotation, you can specify your own arbitrary notation alphabets for your custom unique tokens.
André D wrote:The session.hash_bits_per_character setting lets you pick the notation that is used for displaying these 128 or 160-bit hash digests.
You can also reproduce the exact notation that PHP uses for generating session IDs.
User avatar
kaisellgren
DevNet Resident
Posts: 1675
Joined: Sat Jan 07, 2006 5:52 am
Location: Lahti, Finland.

Re: length of a session ID ...

Post by kaisellgren »

André D wrote:This might be a good place for me to inject a shameless plug for my FixedBitNotation class, which I posted in the Coding Critique forum but no one commented on. :) If you're generating your own random strings using one of the strong techniques Kai talks about all the time, you can use FixedBitNotation to represent it in a customized notation that suits your needs. Whether you're creating unique tokens for use as session IDs, anti-CSRF form IDs, or anything else, I often see people using hexadecimal. Hexadecimal tokens are longer than base-32 or base-64 derived tokens. With FixedBitNotation, you can specify your own arbitrary notation alphabets for your custom unique tokens.
André D wrote:The session.hash_bits_per_character setting lets you pick the notation that is used for displaying these 128 or 160-bit hash digests.
You can also reproduce the exact notation that PHP uses for generating session IDs.
I will have a look at it.

If you need a cryptographically strong RNG, then either use /dev/random on Unix-like systems or CryptoAPI in Windows based systems. The /dev/urandom is not cryptographically secure, but will do for PHP applications.
Post Reply