Computers are deterministic and are therefore predictable. Computers cannot, in and of themselves, generate truly random numbers. In the absence of outside input, computers can only create pseudo-random numbers. In the words of John Von Neumann, “Anyone attempting to produce random numbers by purely arithmetic means is, of course, in a state of sin.”
A random number vulnerability occurs when a program uses a method of generating random numbers which is either:
- Not random
To generate good random numbers, the computer must have two things:
- A good random number generation algorithm
- A random and unpredicatable seed for the random number generation algorithm
Random Number Vulnerability Examples
Consider the following code snippet:
This code generated bad random numbers because when you call rand() before a seed has been established with srand(), it uses the value 1 as a default seed. Anyone else on the same machine with the same compiler who calls rand() with a seed of 1 will get the same random number as you just did.
Let’s look at another code snippet:
srand (time (0)); x=rand();
This code does call srand() with the current time as a seed. However, this code is still insecure because:
- The system time is a very bad seed, because it is predictable within a small range.
- The ANSI C rand() function itself does not generate good random numbers.
Let’s examine a third code snippet:
srandom (time (0)); x=random();
This code uses the BSD random() and srandom() functions, which generate much better random numbers than their ANSI C predecessors. However, this code still uses time() to generate the seed number. A much better source for random numbers on BSD and Linux systems is the /dev/random device.
Number Seeds and Random Number Vulnerabilities
Good seed numbers come from unpredictable events such as user keystrokes or mouse movements. These are not perfect sources of randomness, however. Human behavior is somewhat predictable and computer hardware can buffer keyboard and mouse interrupts, reducing their randomness.
Numerous other random number generators are available for various platforms and development environments. It is extremely difficult to create a good one, and even more difficult to determine if the random number generator you created really is generating random and unpredictable numbers. The best path for most applications is to implement an existing random number generator which has been subject to public cryptanalysis.
Random number vulnerabilities are of interest to hackers when they can be utilized to determine input values to cryptographic functions. This can be utilized in cryptanalysis.
Improper use of the function calls rand() and random() are the normal causes of random number vulnerabilities.
Additional Information Sources on Generating Random Numbers
For more information on generating random numbers, read RFC 1750 – Randomness Recommendations for Security.