Verwendung unzureichend zufälliger Werte
Beschreibung
Verwendung unzureichend zufälliger Werte tritt auf, wenn ein Produkt unzureichend zufällige Zahlen oder Werte in einem Sicherheitskontext verwendet, der von unvorhersagbaren Zahlen abhängt. Kryptografische Operationen, Session-Identifikatoren, Passwort-Reset-Tokens, CSRF-Tokens und andere sicherheitskritische Werte müssen mit kryptografisch sicheren Zufallszahlengeneratoren (CSPRNGs) generiert werden. Wenn vorhersagbare oder Zufallszahlengeneratoren mit niedriger Entropie verwendet werden, können Angreifer zukünftige Werte vorhersagen, aktuelle Werte erraten oder den begrenzten Schlüsselraum per Brute-Force durchsuchen, um Sicherheitsmechanismen zu kompromittieren.
Risiko
Vorhersagbare Zufallswerte untergraben die Sicherheit von Systemen, die auf Unvorhersagbarkeit angewiesen sind. Session-Tokens, die mit schwacher Zufälligkeit generiert werden, können vorhergesagt werden, was Session-Hijacking ermöglicht. CVE-2025-13353 in Cloudflares gokey-Utility reduzierte die Schlüsselentropie von 240 Bytes auf nur 28 Bytes aufgrund fehlerhafter Seed-Ableitung, wodurch Angreifer mit Zugriff auf Seed-Dateien alle Passwörter ohne Master-Passwort wiederherstellen könnten. Passwort-Reset-Tokens mit unzureichender Zufälligkeit können erraten werden. CSRF-Tokens werden unwirksam, wenn sie vorhersagbar sind. Statistische PRNGs wie Pythons random-Modul oder JavaScripts Math.random() können ihren internen Zustand aus der Ausgabe rekonstruieren lassen, was alle zukünftigen Werte vorhersagbar macht.
Lösung
Verwenden Sie immer kryptografisch sichere Zufallszahlengeneratoren (CSPRNGs) für sicherheitsrelevante Operationen. In Python verwenden Sie das secrets-Modul oder os.urandom(). In JavaScript verwenden Sie crypto.getRandomValues() oder crypto.randomBytes(). In Java verwenden Sie SecureRandom. Stellen Sie ausreichende Entropie sicher - verwenden Sie mindestens 128 Bits für Tokens und 256 Bits für kryptografische Schlüssel. Initialisieren Sie CSPRNGs niemals mit vorhersagbaren Werten. Verifizieren Sie, dass die Zufallszahlengenerierung ordnungsgemäß initialisiert ist. Verwenden Sie gut geprüfte Bibliotheken und vermeiden Sie die Implementierung benutzerdefinierter Zufallsgenerierung.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Authentifizierung | Umfang: Session-Hijacking Vorhersagbare Session-Tokens ermöglichen Angreifern, gültige Sessions zu erraten und Benutzer zu imitieren. |
| Zugriffskontrolle | Umfang: Token-Vorhersage Passwort-Reset-Tokens, CSRF-Tokens und API-Schlüssel können vorhergesagt und ausgenutzt werden. |
| Vertraulichkeit | Umfang: Kryptografische Schwäche Schwache zufällige Schlüssel kompromittieren alle Verschlüsselung, die diese Schlüssel verwendet. |
Beispielcode + Korrigierter Code
Anfälliger Code
# ANFÄLLIG: Verwendung des random-Moduls für Sicherheitstokens
import random
import string
def generate_password_reset_token():
# random-Modul ist NICHT kryptografisch sicher!
# Interner Zustand kann aus Ausgabe rekonstruiert werden
chars = string.ascii_letters + string.digits
return ''.join(random.choice(chars) for _ in range(32))
def generate_session_id():
# Vorhersagbar - basiert auf Mersenne Twister
return str(random.randint(0, 999999999))
# ANFÄLLIG: Schwaches Seeding
import time
random.seed(time.time()) # Vorhersagbarer Seed basiert auf Zeit
token = random.randint(0, 2**32)
// ANFÄLLIG: Verwendung von java.util.Random für Sicherheit
import java.util.Random;
public class TokenGenerator {
private Random random = new Random(); // Nicht kryptografisch sicher!
public String generateToken() {
// Vorhersagbar nach Beobachtung einiger Ausgaben
return String.valueOf(random.nextLong());
}
public String generateApiKey() {
// Schwache Zufälligkeit für API-Schlüssel
StringBuilder key = new StringBuilder();
for (int i = 0; i < 32; i++) {
key.append((char) ('a' + random.nextInt(26)));
}
return key.toString();
}
}
// ANFÄLLIG: Math.random() für Sicherheitszwecke
function generateCSRFToken() {
// Math.random() ist NICHT kryptografisch sicher!
return Math.random().toString(36).substring(2);
}
function generateVerificationCode() {
// Niedrige Entropie - nur 6 Ziffern
return Math.floor(Math.random() * 1000000).toString().padStart(6, '0');
}
// ANFÄLLIG: Vorhersagbare UUID-Generierung
function generateSessionId() {
// Verwendung von Zeitstempel und Zähler - leicht vorhersagbar
return Date.now().toString(16) + '-' + (++counter).toString(16);
}
Korrigierter Code
# SICHER: Verwendung des secrets-Moduls für kryptografische Zufälligkeit
import secrets
import string
def generate_password_reset_token_safe():
# secrets-Modul verwendet OS-Entropiequelle
return secrets.token_urlsafe(32) # 256 Bits Entropie
def generate_session_id_safe():
# Kryptografisch sichere zufällige Bytes
return secrets.token_hex(32) # 256-Bit Session-ID
def generate_verification_code_safe():
# Selbst für kurze Codes kryptografische Zufälligkeit verwenden
return ''.join(secrets.choice(string.digits) for _ in range(6))
def generate_api_key_safe():
# Sicheren API-Schlüssel mit ausreichender Entropie generieren
return secrets.token_urlsafe(32) # 256 Bits
// SICHER: Verwendung von SecureRandom für kryptografische Zufälligkeit
import java.security.SecureRandom;
import java.util.Base64;
public class SecureTokenGenerator {
private final SecureRandom secureRandom;
public SecureTokenGenerator() {
// Starke Instanz für bessere Entropie verwenden
try {
this.secureRandom = SecureRandom.getInstanceStrong();
} catch (NoSuchAlgorithmException e) {
this.secureRandom = new SecureRandom();
}
}
public String generateToken() {
byte[] bytes = new byte[32]; // 256 Bits
secureRandom.nextBytes(bytes);
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
}
public String generateApiKey() {
byte[] bytes = new byte[32];
secureRandom.nextBytes(bytes);
return bytesToHex(bytes);
}
public String generateSessionId() {
byte[] bytes = new byte[32];
secureRandom.nextBytes(bytes);
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes);
}
private static String bytesToHex(byte[] bytes) {
StringBuilder hex = new StringBuilder();
for (byte b : bytes) {
hex.append(String.format("%02x", b));
}
return hex.toString();
}
}
// SICHER: Verwendung des crypto-Moduls für sichere Zufälligkeit
const crypto = require('crypto');
function generateCSRFTokenSafe() {
// 256 Bits kryptografische Zufälligkeit
return crypto.randomBytes(32).toString('hex');
}
function generateVerificationCodeSafe() {
// Kryptografisch sichere zufällige Ziffern
const buffer = crypto.randomBytes(4);
const number = buffer.readUInt32BE(0) % 1000000;
return number.toString().padStart(6, '0');
}
function generateSessionIdSafe() {
// crypto.randomUUID() oder randomBytes verwenden
return crypto.randomUUID(); // Node 14.17+
}
// Browser-sichere Version
function generateTokenBrowser() {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
return Array.from(array, b => b.toString(16).padStart(2, '0')).join('');
}
// SICHER: Sichere Passwortgenerierung
function generateSecurePassword(length = 16) {
const charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*';
const randomBytes = crypto.randomBytes(length);
let password = '';
for (let i = 0; i < length; i++) {
password += charset[randomBytes[i] % charset.length];
}
return password;
}
Ausgenutzt in der Praxis
Cloudflare gokey Entropie-Reduktion (Cloudflare, 2025)
CVE-2025-13353 in Cloudflares gokey-Utility (vor 0.2.0) verwendete fehlerhafte Seed-Entschlüsselung, die Passwörter nur aus dem AES-GCM-Authentifizierungs-Tag und IV anstelle der vollen 240-Byte-Seed-Entropie ableitete, was die Schlüsselstärke auf nur 28 Bytes reduzierte und Passwortwiederherstellung ohne Master-Passwort ermöglichte.
PHP Session-ID-Vorhersage (PHP, Historisch)
Historische PHP-Versionen generierten Session-IDs mit schwacher Zufälligkeit, was Angreifern ermöglichte, gültige Session-IDs vorherzusagen und Benutzersitzungen zu kapern. Dies führte zu Verbesserungen in PHPs Session-Management.
OAuth-Token-Vorhersageangriffe (Mehrere, laufend)
Mehrere OAuth-Implementierungen wurden durch vorhersagbare Token-Generierung kompromittiert, wodurch Angreifer Autorisierungscodes und Zugriffstoken fälschen könnten.
Tools zum Testen/Ausnutzen
-
Burp Sequencer — Analyse der Token-Zufälligkeitsqualität.
-
NIST Statistical Test Suite — Testen der Qualität von Zufallszahlengeneratoren.
-
Untwister — Angriff auf Mersenne Twister PRNG.
CVE-Beispiele
-
CVE-2025-13353 — Cloudflare gokey unzureichende Entropie.
-
CVE-2008-2108 — PHP Session-ID-Vorhersage-Schwachstelle.
-
CVE-2019-15847 — GCC schwacher PRNG in Stack-Protector.
Referenzen
-
MITRE. "CWE-330: Use of Insufficiently Random Values." https://cwe.mitre.org/data/definitions/330.html
-
OpenSSF. "Secure Coding Guide for Python - CWE-330." https://best.openssf.org/Secure-Coding-Guide-for-Python/CWE-693/CWE-330/