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

AuswirkungDetails
ZugriffskontrolleUmfang: Zugriffskontrolle

Angreifer können Authentifizierungs-Tokens, Session-IDs und Sequenznummern vorhersagen, was Session-Hijacking, Verbindungs-Spoofing und unbefugten Zugriff ermöglicht.
IntegritätUmfang: Integrität

Vorhersagbare Transaktions- oder Nachrichten-Identifikatoren ermöglichen Request-Forgery, Replay-Angriffe und Injektion bösartiger Daten in Kommunikationsströme.
VerfügbarkeitUmfang: 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


CVE-Beispiele


Referenzen

  1. MITRE Corporation. "CWE-342: Predictable Exact Value from Previous Values." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/342.html

  2. Bellovin, S. "Defending Against Sequence Number Attacks." RFC 1948. https://tools.ietf.org/html/rfc1948

  3. NIST. "Recommendation for Random Number Generation." SP 800-90A. https://csrc.nist.gov/publications/detail/sp/800-90a/rev-1/final