views:

407

answers:

6

Yesterday I asked Are GUIDs generated on Windows 2003 safe to use as session IDs? and the answer combined with combined with this article GUIDs are globally unique, but substrings of GUIDs aren't prompted me to think about replacing my current mechanism of using GUIDs as session ID's in cookies.

Because it's a bit of work to make that change I decided to run a quick GUID test on my Vista PC to see if a sequence of GUIDs was obviously deterministic (what I'm worried about is if an attacker was able to get a sequence of GUIDs generated by my server they would be able to generate new matching ones).

In Raymond Chen's article (which references this very old spec UUIDs and GUIDs from 1998) the GUID is made up of:

  • 60 bits of timestamp,
  • 48 bits of computer identifier,
  • 14 bits of uniquifier, and
  • six bits are fixed

Going by that if I generate 10 GUIDs the first 15 ASCII chars (excluding '-') are the timestamp, the next 12 ASCII chars are the computer identifier, the next 3.5 ASCII characters are random and the last 1.5 characters are fixed.

Getting 10 GUIDs on my Vista PC using the .Net System.Guid.NewGuid() yields:

b4e95ead-3619-4dc2-9102-cf7ab0efd927
a45ee719-decd-46b2-8355-7becbe406f74
9af68d75-35a0-4907-b6ab-f15e33acfe96
bed88fa3-3209-4a19-97dd-85d5428ea5f4
123cb39b-8d81-41c6-8894-f1257a8f7606
e2b1f6b1-5791-4a18-80a9-5dc668574ecb
c52aa660-2629-4659-bb83-5583081e5a1c
76eda32d-ceda-412e-8ade-30c47416e954
cbc4d45e-7281-40d2-9f90-00539b04fe98
be36524c-267c-4791-bc9e-3c20b29d7615

The only discernible pattern from a quick visual inspection is that the 13th ASCII character is always 4.

I'm again left wondering if relying on System.Guid to generate pseudo random session IDs is strong enough to protect a web application where cracking a session ID would be worth at most thousands of dollars?

Update: Instead of using a GUID I now plan to generate my session ID's using the approach below. I'm converting the 384 bit random number to a 0x00 byte string so that it's suitable for use in an HTTP cookie.

RNGCryptoServiceProvider rngProvider = new RNGCryptoServiceProvider();
byte[] myKey = new byte[48];
rngProvider.GetBytes(myKey);
string sessionID = null;
myKey.ToList().ForEach(b => sessionID += b.ToString("x2"));
Console.WriteLine(sessionID);
+4  A: 

It's not a complete answer, but I can tell you that the 13th hex digit is always 4 because it denotes the version of the algorithm used to generate the GUID (id est, v4); also, and I quote Wikipedia:

Cryptanalysis of the WinAPI GUID generator shows that, since the sequence of V4 GUIDs is pseudo-random, given the initial state one can predict up to the next 250 000 GUIDs returned by the function UuidCreate. This is why GUIDs should not be used in cryptography, e.g., as random keys.

The rest of the article, and its references: http://en.wikipedia.org/wiki/Guid

--Edit--

From a security standpoint, I'd suggest that you generate your session ID however you feel like, then cryptographically sign it; that way you can pack in whatever information you want and then just slap a signature on the end - the possible issue being the tradeoff between the size/strength of your key and the resulting size of the cookie. GUIDs are useful as IDs, but I'd only rely on a dedicated cryptographic technique for security.

FacticiusVir
A: 

The short answer is, no guid's aren't sufficiently strong to generate session id's if you want to prevent session id guessing and cracking.

For the same reason why you wouldn't want to use a GUID as an AES key, you don't want to use them for any type of sensitive identifies.

A GUID works extremely well for what they are designed to be: A mathematically guarenteed unique ID to never repeat.

Even if cracking a session ID is only worth $1000, imagine if thats done 100 times. Now you're talking serious bling.

I know it's an easy way out to use GUID's but resist, and deal with the pain by taking the proper precautions to adequately secure your application. Your users will thank you.

Alan
No one can guess what a guid is before hand..so why isnt it good to use a guid in a session?
The point is that someone _can_ "guess" what a GUID is in advance, so long as they know a GUID that was generated on the same machine a short time previously.
FacticiusVir
@FacticiusVir - Is there any documentation of this?
+1  A: 

Some notes:

  1. I doubt that any implementation of GUIDs was designed to be cryptograhpically secure. (And this supposition would be borne out by the article linked for the next item.)
  2. The 13th ASCII character is a signifier of what algorithm was used to generate the GUID.

If you're really concerned with having strong session IDs, then perhaps a cryptographically secure hash of something that cannot be determined from off-machine would be your best approach. Perhaps generating a one-time pad from some internal document or data source would even work.

Lee
sipwiz
Why involve a GUID at all? What are you trying to do?
Noon Silk
A: 

What are you trying to do? Do you want just a source of random numbers?

Check out random.org and hotbits. Many many years ago, I had a Java library that would gather numbers from these sources, and join them together, to get a quite beautiful random series (though it assumes the two sites aren't in cahootz).

Noon Silk
I think you'll find that random numbers are much easier to generate: http://xkcd.com/221/
FacticiusVir
A: 

It is almost impossible to get a duplicate guid considering the possiblities of getting one. Here are some quick math facts

Grains of sand in the world 75,000,000,000,000,000,000

Number of GUIDs 340,282,366,920,938,463,463,374,607,431,770,000,000

There are enough unique GUIDs to assign one to each star in the known universe, and still have the vast majority spare. However, if you "drew" a line from each star in the known universe to every other star, there would not be enough GUIDs to uniquely identify them.
FacticiusVir
if X is the number of stars in the universe then if you draw a line from every star to every other star there would be X^X points or X to the power of X which is a really really really big number. I would be surprised if the number is not a googleplex(a one with a hundred zeros behind it).
I believe the estimate of the number of stars is 3-7 x10 ^22, which would put the number of lines between them at 9-49 x10 ^44; less than the square root of a _googol_. A googolplex (do note the spelling) is 1 x10 ^googol, or a one with googol zeroes after it.
FacticiusVir
Sorry, I've messed that calculation up completely *facepalm*
FacticiusVir
FacticiusVir
OK..I though you were talking about the number points that connect the lines together. The number of lines is different and will be a much smaller number. But, when we are dealing with such huge numbers it becomes unreachable for humans and computers. I can easily think of scenarios where a guid would not be able to fullfill. How about uniquely identifying each and every electron in the world. There is not enough guids for that.
@FacticiusVir The number of lines between N stars will be N*(N-1)/2, as you say. However, this is unfortunately not equal to (N-1)! = (N-1)*(N-2)*(N-3)*(N-4)*...
norheim.se
+2  A: 

I suggest you use the System.Security.Cryptography.RandomNumberGenerator. This is designed to produce numbers which can't be reverse engineered. Guid's motivation is to be unique. You could combine both the GUID and secure random number, but a 128 bit secure random number is never going to have a collision on practice.

brianegge