Vorhersagbarer exakter Wert aus vorherigen Werten
Beschreibung
Vorhersagbarer exakter Wert aus vorherigen Werten ist eine Schwachstelle, die auftritt, wenn ein exakter Wert oder eine Zufallszahl durch Beobachtung vorheriger vom System generierter Werte präzise vorhergesagt werden kann. Diese Schwäche zeigt einen fundamentalen Fehler im Zufallszahlen-Generierungsschema an, bei dem die Sequenz einem deterministischen Muster folgt, das Angreifer analysieren und ausnutzen können. Häufige Manifestationen umfassen lineare Kongruenzgeneratoren mit beobachtbarer Ausgabe, sequenzielle Zähler mit geringfügiger Verschleierung, TCP-Sequenznummern mit vorhersagbaren Inkrementen und andere Schemata, bei denen mathematische Beziehungen zwischen aufeinanderfolgenden Ausgaben die Vorhersage zukünftiger Werte mit vollständiger Genauigkeit ermöglichen.
Risiko
Wenn exakte Werte aus vorherigen Beobachtungen vorhergesagt werden können, sind Sicherheitsmechanismen, die auf diesen Werten basieren, vollständig kompromittiert. Vorhersagbare TCP-Initial-Sequenznummern ermöglichen Verbindungs-Hijacking und IP-Spoofing-Angriffe. Vorhersagbare DNS-Query-IDs ermöglichen DNS-Cache-Poisoning und leiten Opfer auf bösartige Server um. Sequenzielle Transaktions-IDs ermöglichen Transaktionsfälschung und Replay-Angriffe. Authentifizierungs-Tokens, die vorhersagbaren Mustern folgen, ermöglichen Kontoübernahme. Das Risiko ist schwerwiegend, da die Vorhersage exakt und nicht probabilistisch ist - Angreifer müssen keinen Wertebereich per Brute-Force durchsuchen, sondern können den nächsten Wert präzise berechnen. Historische Angriffe auf TCP-Sequenznummern-Vorhersage führten zu weitreichenden Sicherheitsverbesserungen in Betriebssystemen und demonstrieren die reale Auswirkung dieser Schwachstelle.
Lösung
Verwenden Sie kryptografisch sichere Zufallszahlengeneratoren, die Ausgaben ohne beobachtbare mathematische Beziehung zwischen aufeinanderfolgenden Werten erzeugen. Stellen Sie sicher, dass jeder generierte Wert mindestens 128 Bits Entropie aus ordnungsgemäßen Entropiequellen hat. Für Protokolle, die Sequenznummern erfordern, integrieren Sie zufällige Komponenten, die nicht aus vorherigen Werten abgeleitet werden können. Implementieren Sie FIPS 140-2 konforme Zufallszahlengeneratoren. Bei Verwendung von PRNGs stellen Sie ordnungsgemäßes Seeding aus Hardware-Entropiequellen und periodisches Re-Seeding sicher. Vermeiden Sie lineare Kongruenzgeneratoren und andere schwache PRNGs für sicherheitsrelevante Zwecke. Führen Sie Sicherheitsanalysen von Zahlen-Generierungsschemata durch, um potenzielle Vorhersageangriffe zu identifizieren.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Umfang: Zugriffskontrolle Angreifer können Authentifizierungs-Tokens, Session-IDs und Sequenznummern vorhersagen, was Session-Hijacking, Verbindungs-Spoofing und unbefugten Zugriff ermöglicht. |
| Integrität | Umfang: Integrität Vorhersagbare Transaktions- oder Nachrichten-Identifikatoren ermöglichen Request-Forgery, Replay-Angriffe und Injektion bösartiger Daten in Kommunikationsströme. |
| Verfügbarkeit | Umfang: Verfügbarkeit Vorhersagbare Sequenznummern in Protokollen können Verbindungs-Reset-Angriffe und andere Denial-of-Service-Techniken ermöglichen. |
Beispielcode
Anfälliger Code (C/Python)
Die folgenden Beispiele demonstrieren vorhersagbare Wertgenerierung:
// Anfällig: Vorhersagbare Sequenznummern
#include <stdio.h>
#include <stdlib.h>
// Anfällig: Einfache inkrementierende Sequenz
static unsigned int sequence_number = 0;
unsigned int vulnerable_get_sequence() {
// Anfällig: Nächster Wert ist exakt aktuell + 1
return ++sequence_number;
}
// Anfällig: Linearer Kongruenzgenerator (LCG)
static unsigned int lcg_state = 1;
unsigned int vulnerable_lcg_next() {
// Anfällig: Zustand kann aus jedem beobachteten Wert berechnet werden
lcg_state = lcg_state * 1103515245 + 12345;
return lcg_state;
}
// Anfällig: Vorhersagbare TCP-ähnliche Sequenznummer
static unsigned int tcp_seq = 0;
unsigned int vulnerable_tcp_sequence() {
// Anfällig: Inkrement ist vorhersagbar
tcp_seq += 64000; // Festes Inkrement
return tcp_seq;
}
// Anfällig: Zeit-basiert mit festem Inkrement
static unsigned int counter = 0;
unsigned int vulnerable_time_counter() {
// Anfällig: Sowohl Zeit als auch Inkrement sind vorhersagbar
counter++;
return (unsigned int)time(NULL) * 1000 + counter;
}
// Anfällig: XOR mit vorhersagbarem Schlüssel
static unsigned int obfuscated_counter = 0;
const unsigned int XOR_KEY = 0xDEADBEEF;
unsigned int vulnerable_obfuscated() {
// Anfällig: XOR ist reversibel, Sequenz immer noch vorhersagbar
obfuscated_counter++;
return obfuscated_counter ^ XOR_KEY;
}
// Anfällig: Modulare Arithmetik-Sequenz
static unsigned int mod_counter = 0;
unsigned int vulnerable_modular() {
// Anfällig: Nächster = (aktuell + 7) mod 256
mod_counter = (mod_counter + 7) % 256;
return mod_counter;
}
# Anfällig: Vorhersagbare Wertgenerierung in Python
import time
# Anfällig: Einfacher sequenzieller Generator
class VulnerableSequential:
def __init__(self):
self.counter = 0
def next(self):
# Anfällig: Exakt vorhersagbar
self.counter += 1
return self.counter
# Anfällig: LCG-Implementierung
class VulnerableLCG:
def __init__(self, seed=1):
self.state = seed
def next(self):
# Anfällig: Standard-LCG-Parameter
# Nächster Zustand = (a * Zustand + c) mod m
self.state = (self.state * 1103515245 + 12345) & 0x7FFFFFFF
return self.state
def predict_next(self, observed):
# Angriff: Kann nächsten aus jedem beobachteten Wert vorhersagen
return (observed * 1103515245 + 12345) & 0x7FFFFFFF
# Anfällig: Alternierendes Inkrement-Muster
class VulnerableAlternating:
def __init__(self):
self.counter = 0
self.increment = 1
def next(self):
# Anfällig: Muster ist alternierend +1, +2, +1, +2...
self.counter += self.increment
self.increment = 3 - self.increment # Wechselt zwischen 1 und 2
return self.counter
# Anfällig: Zeit-Division-Multiplexing
class VulnerableTimeDivision:
def __init__(self):
self.sequence = 0
def next(self):
# Anfällig: Zeit-Komponente ist beobachtbar
self.sequence += 1
timestamp = int(time.time())
return (timestamp << 16) | (self.sequence & 0xFFFF)
# Anfällig: LFSR (Linear Feedback Shift Register)
class VulnerableLFSR:
def __init__(self, seed=1):
self.state = seed
def next(self):
# Anfällig: LFSR ist mathematisch vorhersagbar
bit = ((self.state >> 0) ^ (self.state >> 2) ^
(self.state >> 3) ^ (self.state >> 5)) & 1
self.state = (self.state >> 1) | (bit << 15)
return self.state
// Anfällig: Vorhersagbare Wertgenerierung in Java
public class VulnerablePredictable {
// Anfällig: Sequenzieller Zähler
private static long counter = 0;
public static long vulnerableSequential() {
// Anfällig: Nächster ist exakt aktuell + 1
return ++counter;
}
// Anfällig: java.util.Random ist LCG-basiert
private java.util.Random rand = new java.util.Random();
public long vulnerableRandom() {
// Anfällig: Random verwendet intern 48-Bit LCG
// Zustand kann aus beobachteten Ausgaben wiederhergestellt werden
return rand.nextLong();
}
// Anfällig: Vorhersagbare Hash-basierte Sequenz
private long hashCounter = 0;
public String vulnerableHashSequence() {
// Anfällig: Hash von sequenzieller Eingabe ist immer noch sequenziell
hashCounter++;
return Integer.toHexString((int)hashCounter);
}
// Anfällig: Zeit-basiert mit Zähler
private int timeCounter = 0;
public long vulnerableTimeCounter() {
// Anfällig: Beide Komponenten sind vorhersagbar
timeCounter++;
return System.currentTimeMillis() * 1000 + timeCounter;
}
// Anfällig: Fester Offset-Sequenz
private long offsetCounter = 1000000;
public long vulnerableOffset() {
// Anfällig: Fester Offset fügt keine Entropie hinzu
return offsetCounter++;
}
}
Korrigierter Code (C/Python)
// Korrigiert: Unvorhersagbare Wertgenerierung
#include <openssl/rand.h>
#include <stdio.h>
// Korrigiert: Kryptografisch zufällige Sequenznummern
int secure_sequence(unsigned int *seq) {
// Korrigiert: Jeder Wert ist unabhängig und unvorhersagbar
unsigned char bytes[4];
if (RAND_bytes(bytes, sizeof(bytes)) != 1) {
return -1;
}
*seq = (bytes[0] << 24) | (bytes[1] << 16) |
(bytes[2] << 8) | bytes[3];
return 0;
}
// Korrigiert: Zufall mit Zähler für Eindeutigkeit
typedef struct {
unsigned int random_base;
unsigned int counter;
} SecureSequence;
int secure_init(SecureSequence *seq) {
unsigned char bytes[4];
if (RAND_bytes(bytes, sizeof(bytes)) != 1) {
return -1;
}
seq->random_base = (bytes[0] << 24) | (bytes[1] << 16) |
(bytes[2] << 8) | bytes[3];
seq->counter = 0;
return 0;
}
unsigned int secure_next(SecureSequence *seq) {
// Korrigiert: Zufallsbasis stellt Unvorhersagbarkeit sicher
// Zähler stellt Eindeutigkeit sicher
seq->counter++;
return seq->random_base ^ seq->counter;
}
// Korrigiert: TCP-ähnliche Sequenz mit zufälligem Inkrement
int secure_tcp_sequence(unsigned int *current_seq) {
unsigned char random_increment[4];
if (RAND_bytes(random_increment, sizeof(random_increment)) != 1) {
return -1;
}
// Korrigiert: Zufälliges Inkrement zwischen 1 und 2^31
unsigned int increment = (random_increment[0] << 24) |
(random_increment[1] << 16) |
(random_increment[2] << 8) |
random_increment[3];
increment = (increment & 0x7FFFFFFF) | 1; // Mindestens 1
*current_seq += increment;
return 0;
}
// Korrigiert: Vollständig zufällige Werte
int secure_random_value(unsigned char *buffer, size_t len) {
// Korrigiert: Keine mathematische Beziehung zwischen Werten
return RAND_bytes(buffer, len) == 1 ? 0 : -1;
}
# Korrigiert: Unvorhersagbare Wertgenerierung in Python
import secrets
import os
import hashlib
# Korrigiert: Kryptografisch sicherer Zufall
class SecureRandom:
@staticmethod
def next():
# Korrigiert: Jeder Wert unabhängig und unvorhersagbar
return secrets.randbits(64)
# Korrigiert: Sichere Sequenz mit zufälliger Basis
class SecureSequence:
def __init__(self):
# Korrigiert: Zufällige Basis verhindert Vorhersage
self.random_base = secrets.randbits(64)
self.counter = 0
def next(self):
self.counter += 1
# Korrigiert: Selbst bei bekanntem Zähler verhindert random_base Vorhersage
combined = f"{self.random_base}:{self.counter}"
return hashlib.sha256(combined.encode()).hexdigest()
# Korrigiert: Sichere TCP-ähnliche Sequenz
class SecureTCPSequence:
def __init__(self):
self.sequence = secrets.randbits(32)
def next(self):
# Korrigiert: Zufälliges Inkrement
increment = secrets.randbelow(2**31) + 1
self.sequence = (self.sequence + increment) & 0xFFFFFFFF
return self.sequence
# Korrigiert: Token-Generierung ohne Vorhersagbarkeit
class SecureTokenGenerator:
@staticmethod
def generate():
# Korrigiert: Reiner Zufall, keine sequenzielle Komponente
return secrets.token_hex(32)
# Korrigiert: UUID-basierte Identifikatoren
import uuid
class SecureIdentifier:
@staticmethod
def generate():
# Korrigiert: UUID4 verwendet sicheren Zufall
return str(uuid.uuid4())
# Korrigiert: HMAC-basierte Sequenz
class SecureHMACSequence:
def __init__(self):
import hmac
self.key = os.urandom(32)
self.counter = 0
def next(self):
self.counter += 1
# Korrigiert: HMAC stellt Unvorhersagbarkeit ohne Schlüssel sicher
import hmac
h = hmac.new(self.key, str(self.counter).encode(), hashlib.sha256)
return h.hexdigest()
// Korrigiert: Unvorhersagbare Wertgenerierung in Java
import java.security.SecureRandom;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public class SecurePredictable {
private static final SecureRandom secureRandom = new SecureRandom();
// Korrigiert: Kryptografisch sicherer Zufall
public static long secureRandom() {
// Korrigiert: SecureRandom liefert unvorhersagbare Werte
return secureRandom.nextLong();
}
// Korrigiert: Sichere Sequenz mit zufälliger Basis
private long randomBase;
private long counter;
public SecurePredictable() {
this.randomBase = secureRandom.nextLong();
this.counter = 0;
}
public long secureNext() {
counter++;
// Korrigiert: Zufällige Basis verhindert Vorhersage
return randomBase ^ counter ^ secureRandom.nextLong();
}
// Korrigiert: UUID für Identifikatoren
public static String secureIdentifier() {
// Korrigiert: UUID4 verwendet SecureRandom
return UUID.randomUUID().toString();
}
// Korrigiert: HMAC-basierte Sequenz
private byte[] hmacKey;
public void initHMAC() {
hmacKey = new byte[32];
secureRandom.nextBytes(hmacKey);
}
public String secureHMACNext() throws Exception {
counter++;
Mac mac = Mac.getInstance("HmacSHA256");
SecretKeySpec keySpec = new SecretKeySpec(hmacKey, "HmacSHA256");
mac.init(keySpec);
byte[] result = mac.doFinal(Long.toString(counter).getBytes());
return bytesToHex(result);
}
// Korrigiert: Sichere TCP-ähnliche Sequenz
private int tcpSequence;
public int secureTcpNext() {
// Korrigiert: Zufälliges Inkrement
int increment = secureRandom.nextInt(Integer.MAX_VALUE) + 1;
tcpSequence += increment;
return tcpSequence;
}
private String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}
Die Korrektur verwendet kryptografisch sichere Zufallsgenerierung, bei der Werte keine mathematische Beziehung zu vorherigen Ausgaben haben.
Ausgenutzt in der Praxis
Vorhersagbare TCP-Sequenznummern (CVE-2002-1463)
Eine Firewall generierte vorhersagbare TCP-Initial-Sequenznummern, was es Angreifern ermöglichte, Pakete in bestehende Verbindungen zu injizieren oder Sessions zu übernehmen.
DNS Query-ID-Vorhersage (CVE-2000-0335)
DNS-Resolver mit vorhersagbaren Query-IDs ermöglichten Angreifern, DNS-Antworten zu fälschen und Opfer auf bösartige Server umzuleiten.
Tools zum Testen/Ausnutzen
-
Scapy — Netzwerkpaket-Manipulation zum Testen der Sequenznummer-Vorhersagbarkeit.
-
Statistische Analyse-Tools — Analysiert Sequenzen auf mathematische Muster.
-
Sequenz-Vorhersage-Skripte — Testet LCG und andere vorhersagbare Sequenzen.
CVE-Beispiele
-
CVE-2002-1463 — Firewall vorhersagbare TCP-Sequenznummern.
-
CVE-1999-0077 — Vorhersagbare TCP-Sequenzen ermöglichen Spoofing.
-
CVE-2000-0335 — Vorhersagbare DNS-Query-IDs.
Referenzen
-
MITRE Corporation. "CWE-342: Predictable Exact Value from Previous Values." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/342.html
-
Bellovin, S. "Defending Against Sequence Number Attacks." RFC 1948. https://tools.ietf.org/html/rfc1948
-
NIST. "Recommendation for Random Number Generation." SP 800-90A. https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final