Weakness reference
CWE-330

Use of Insufficiently Random Values

This weakness occurs when software relies on random numbers or values for security purposes—such as session tokens, password reset links, or cryptographic…

01Summary

This weakness occurs when software relies on random numbers or values for security purposes—such as session tokens, password reset links, or cryptographic keys—but generates them using methods that are predictable or have insufficient entropy. An attacker who can predict these values can bypass authentication, hijack sessions, or forge credentials without needing to break the underlying encryption.

02How It Happens

Security-critical random values must be generated using cryptographically secure sources of randomness. Many programming languages provide "convenience" random functions (like random() in Python or rand() in PHP) that are designed for simulations and games, not security. These functions often rely on weak seeds, have limited output ranges, or use algorithms that are mathematically predictable. When developers use these functions to generate session IDs, password reset tokens, or API keys, an attacker can observe a few outputs, reverse-engineer the internal state, and predict all future values. The problem is compounded if the seed itself is weak—for example, seeded from the current time, which an attacker can easily guess.

03Real-World Impact

Predictable session tokens allow attackers to forge valid sessions and impersonate legitimate users without knowing their passwords. Weak password reset tokens can be brute-forced or predicted, enabling account takeover. Predictable API keys or OAuth tokens expose integrations and third-party access. In cryptographic contexts, weak random number generation undermines the entire security model, potentially allowing decryption of supposedly encrypted data. The impact ranges from account compromise to full system breach, depending on what the random value protects.

04Vulnerable & Fixed Patterns

Vulnerable pattern
import random
import string

def generate_session_token():
    # Weak: uses non-cryptographic random
    random.seed()
    token = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(32))
    return token

def generate_reset_link(user_id):
    # Weak: predictable token based on time
    import time
    token = str(int(time.time())) + str(user_id)
    return f"https://example.com/reset?token={token}"

Why it's vulnerable:
random.choice() uses the Mersenne Twister algorithm, which is not cryptographically secure and can be predicted after observing a few outputs. Time-based tokens are trivial to guess.

Fixed pattern
import secrets
import string

def generate_session_token():
    # Secure: uses cryptographic random
    token = ''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(32))
    return token

def generate_reset_link(user_id):
    # Secure: uses cryptographically random token
    token = secrets.token_urlsafe(32)
    return f"https://example.com/reset?token={token}"
Vulnerable pattern
<?php
function generate_session_token() {
    // Weak: uses non-cryptographic random
    $token = '';
    for ($i = 0; $i < 32; $i++) {
        $token .= chr(rand(65, 122));
    }
    return $token;
}

function generate_reset_link($user_id) {
    // Weak: predictable token based on time
    $token = time() . '_' . $user_id;
    return "https://example.com/reset?token=" . $token;
}
?>

Why it's vulnerable:
rand() is not cryptographically secure and can be predicted. Time-based tokens are easily guessable.

Fixed pattern
<?php
function generate_session_token() {
    // Secure: uses cryptographic random
    return bin2hex(random_bytes(16));
}

function generate_reset_link($user_id) {
    // Secure: uses cryptographically random token
    $token = bin2hex(random_bytes(32));
    return "https://example.com/reset?token=" . $token;
}
?>

05Prevention Checklist

Use only cryptographically secure random functions: secrets module in Python, random_bytes() in PHP, or equivalent in other languages.
Never seed random number generators with predictable values like timestamps or user IDs.
Generate tokens with sufficient length (at least 128 bits of entropy for session tokens and reset links).
Avoid custom random number generation logic; rely on platform-provided cryptographic libraries.
Review all security-critical random values in your codebase and replace weak generators with secure alternatives.
Store tokens securely (hashed in a database) rather than in plaintext, so even if the generation is observed, the stored value cannot be reused.

06Signs You May Already Be Affected

Look for use of random(), rand(), or mt_rand() in session management, password reset, or token generation code. Check application logs for unusual patterns of session hijacking or account access from unexpected locations. If you find time-based or sequential tokens in your codebase, or tokens that can be brute-forced in a reasonable timeframe, your application is likely vulnerable.

07Related Recent Vulnerabilities