13

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);
Community
  • 1
  • 1
sipsorcery
  • 30,273
  • 24
  • 104
  • 155
  • A GUID is completely deterministic, otherwise it couldn't be a G and a U it would just be an ID. – Noon Silk Sep 09 '09 at 23:58
  • A GUID is deterministic _in space and time_; so if the time at which it was generated was random (which is a good a basis as you'll get for most pseudo-random generators) the GUID is, well, pseudo-random. – FacticiusVir Sep 10 '09 at 00:11
  • When you are dealing with computer generated numbers it will never be truelly random. Some human interaction is preferred to make it closer to true random. Just to let you know there will never be a truelly random number. If so, man will discover what infinty is. – user161433 Sep 10 '09 at 00:27
  • 5
    You have evidently never met my computer. Some of the things it does are truly, truly random. – FacticiusVir Sep 10 '09 at 00:28
  • I mean from a mathematical stand point. a human can generate a number more random then a computer – user161433 Sep 10 '09 at 01:03
  • @luke: You never asked people for a random number, right? ;-) – Joey Mar 23 '10 at 20:08
  • I like your new implementation. I used a StringBuilder to speed it up a bit. – Evan M Mar 11 '11 at 19:35

6 Answers6

10

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
  • 2,037
  • 15
  • 28
7

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
  • 29,240
  • 13
  • 74
  • 99
1

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
  • 18,529
  • 6
  • 58
  • 60
0

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
  • 54,084
  • 6
  • 88
  • 105
-1

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
  • 45,915
  • 17
  • 113
  • 134
-1

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

user161433
  • 4,419
  • 5
  • 32
  • 55
  • 1
    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 Sep 10 '09 at 00:08
  • 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). – user161433 Sep 10 '09 at 00:15
  • 1
    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 Sep 10 '09 at 00:27
  • Sorry, I've messed that calculation up completely *facepalm* – FacticiusVir Sep 10 '09 at 00:35
  • 1
    The correct calculation is: the number of lines between _n_ points is _(n-1)!_, or the factorial of _n-1_. This can be simplified to _n x((n-1)/2)_, so the estimate shifts to between 4.5 x10 ^44 & 2.45 x10 ^45. The point still stands, however, and this is getting vastly off-topic. – FacticiusVir Sep 10 '09 at 00:44
  • 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. – user161433 Sep 10 '09 at 01:00
  • @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)*... – SteinNorheim Oct 01 '09 at 17:50