CWE-337, Predictable Seed in PRNG, is a generator initialized from a predictable seed, such as the process ID or system time.
The range of such seeds is small. That makes this one of the more practical attacks on weak randomness, and it affects anything that generates keys, tokens or passwords at a moment an attacker can estimate.
How it happens
A developer needs a seed and picks a value that is easy to get: the current time, the process ID, a counter. Those values feel unique. But MITRE points out that predictable seeds significantly reduce the number of possible seeds an attacker needs to test to predict which numbers the generator will produce.
/* Vulnerable: seed from time */
srand(time(NULL));
int token = rand();
The observed examples span years:
- CVE-2008-0166: the removal of a couple of lines of code caused Debian's OpenSSL package to use only the current process ID for seeding.
- CVE-2019-11495: a server used erlang:now() to seed the generator, producing a small search space for seeds.
- CVE-2020-7010: a cloud application on Kubernetes generated passwords with a weak generator based on deployment time.
The Debian case is a useful lesson. A small change to a dependency altered how seeding worked, and every user of the package inherited it. Seeding bugs can arrive through updates, not only through your own code.
What an attacker gains
The record's impact is listed as varying by context. In practice, attackers who can bound the seed regenerate the same sequence and recover whatever secrets came from it, which can include keys and session tokens.
How to find it
Static analysis can find some cases of seeding from time or process ID. Look for srand, seed and time or getpid on the same line. For dependencies, watch security advisories on cryptographic and random number libraries, and scan your dependency list for known issues. The free scan runs in your browser for up to 100 dependencies, with no login.
How to fix it
MITRE's mitigations:
- Use non-predictable inputs for seed generation.
- Use products or modules that conform to FIPS 140-2, or the more recent FIPS 140-3 if possible.
- Use a PRNG that periodically re-seeds itself from high quality sources, such as hardware devices with high entropy. But do not re-seed too frequently, or the entropy source might block.
Day to day, skip manual seeding. Ask the operating system.
/* Fixed: Linux getrandom */
#include <sys/random.h>
uint8_t buf[32];
getrandom(buf, sizeof buf, 0);
Quick check
Why not seed from time plus process ID together?
Both are guessable. Combining two guessable values still leaves a small space.
Why does MITRE warn against re-seeding too often?
Entropy sources are limited, so frequent re-seeding can make them block, which becomes an availability problem.