Safeguard
Application Security•

CWE-330 Insufficiently Random Values: Tokens Attackers Can Guess

Session IDs, reset tokens and keys all depend on unpredictable numbers. CWE-330 shows how weak randomness breaks them and how to generate values safely.

Safeguard Security Team
4 min read

CWE-330, Use of Insufficiently Random Values, applies when a product uses numbers or values that are not random enough in a context where unpredictability is the security property. It is a parent to many of the narrower randomness weaknesses covered by the CWEs that follow it.

Almost every application has such a context: session identifiers, password reset links, API keys, CSRF tokens, encryption keys and invitation codes.

How it happens

Developers reach for the language's easy random function. In most languages that function is a statistical generator designed for speed and distribution, not for resisting an attacker. If an attacker sees a few outputs, or can guess the seed, the next values follow.

// Vulnerable: Mersenne Twister is not for secrets
$token = md5(mt_rand());
# Vulnerable: random is a statistical PRNG
import random
reset_token = "".join(random.choices("abcdef0123456789", k=16))

The observed examples are all of this kind. CVE-2021-3692 is a PHP framework using mt_rand() when generating tokens. CVE-2020-7010 is a cloud application on Kubernetes that generated passwords with a weak generator based on deployment time. CVE-2009-3278 is a crypto product using the C rand() function to generate a recovery key, which made brute force easier.

What an attacker gains

The record describes three outcomes:

  • When a protection mechanism relies on random values to restrict access to a resource, such as a session ID or a seed for generating a cryptographic key, an attacker who guesses the value can bypass protection.
  • If a product relies on unique, unguessable IDs to identify a resource, an attacker might guess an ID and access that resource.
  • When an authorization or authentication mechanism relies on random values, a predictable value can let the attacker gain privileges or assume another identity.

How to find it

MITRE lists black box monitoring, static analysis of binaries or bytecode, manual static analysis and dynamic analysis with manual interpretation.

Practical checks:

  1. Search for rand, random, mt_rand and Math.random in code that creates tokens, IDs, passwords or keys.
  2. Collect a few hundred tokens from a test system and look for patterns, such as sequences, timestamps or short ranges.
  3. Check where a seed comes from. A seed from time or process ID is guessable.

How to fix it

MITRE's guidance:

  1. Use a well vetted algorithm that experts currently consider strong, with well tested implementations and adequate length seeds. If a generator is not advertised as cryptographically secure, it is probably a statistical generator and does not belong in security contexts.
  2. Remember that generators can produce predictable numbers if the generator is known and the seed can be guessed. MITRE offers a 256-bit seed as a good starting point.
  3. Consider a generator that re-seeds itself from high quality sources, such as hardware devices.
  4. Use products or modules that conform to FIPS 140-2 to avoid obvious entropy problems, and consult its approved random number generator list.

In code, that means the operating system secure source:

# Fixed: secrets module draws from the OS CSPRNG
import secrets
reset_token = secrets.token_urlsafe(32)
// Fixed: Node crypto
const token = require("crypto").randomBytes(32).toString("hex");
// Fixed: PHP
$token = bin2hex(random_bytes(32));

Quick check

Is a long random looking string always safe?

No. Length does not help if the source is predictable. A 32 character string built from a weak generator can still be guessed.

Where do dependencies come in?

Frameworks can generate tokens for you, as the PHP framework case shows. When a framework or library is the weak source, you have to upgrade it. Scanning your dependency list will show known issues, and the free in-browser scan at gold.safeguard.sh/scan does that for up to 100 dependencies without a login.

Sources

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.