Pseudo random number generators use mathematical algorithms to produce a sequence of numbers with good statistical properties, but the numbers produced are not genuinely random.
The C Standard function rand
(available in stdlib.h
) does not have good random number properties. The numbers generated by rand
have a comparatively short cycle, and the numbers may be predictable. To achieve the best random numbers possible, an implementation-specific function must be used.
Non-Compliant Code Example
The following code generates an ID with a numeric part produced by calling the rand()
function. The IDs produced are predictable and have limited randomness.
enum {len = 12}; char id[len]; /* id will hold the ID, starting with the characters "ID" */ /* followed by a random integer */ int r; int num; /* ... */ r = rand(); /* generate a random integer */ num = snprintf(id, len, "ID%-d", r); /* generate the ID */ /* ... */
Non-Compliant Code Example (BSD)
A better pseudo random number generator is the BSD function random()
.
enum {len = 12}; char id[len]; /* id will hold the ID, starting with the characters "ID" */ /* followed by a random integer */ int r; int num; /* ... */ srandom(time(0)); /* seed the PRNG with the current time */ /* ... */ r = random(); /* generate a random integer */ num = snprintf(id, len, "ID%-d", r); /* generate the ID */ /* ... */
However, the random()
function uses time(0)
as seed. With a trivial seed like time(0)
, however, the results from random()
are also predictable.
Compliant Solution (Linux)
To generate an unpredictable number, use an unpredictable seed and a cryptographically strong mixing function. On Unix systems, for example, decent results can be obtained by reading /dev/urandom
, which will not block the application.
When unpredictability really matters (session IDs and crypto keys) use a cryptographical library and seed it with data that are read from /dev/random
.
The /dev/random
device may block for a long time if there are not enough events going on to generate sufficient randomness; /dev/urandom
does not block.)
The rand48
family of functions provides another alternative.
Risk Assessment
Using the rand()
function leads to possibly predictable random numbers.
Rule |
Severity |
Likelihood |
Remediation Cost |
Priority |
Level |
---|---|---|---|---|---|
MSC30-C |
1 (low) |
1 (unlikely) |
1 (high) |
P1 |
L3 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
References
[[ISO/IEC 9899-1999]] Section 7.20.2.1, "The rand function"
MSC13-A. Detect and remove unused values 14. Miscellaneous (MSC) MSC31-C. Ensure that return values are compared against the proper type