This weakness occurs when software relies on random numbers or values for security purposes—such as session tokens, password reset links, or cryptographic…
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.