Vorhersagbarer Wertebereich aus vorherigen Werten
Beschreibung
Vorhersagbarer Wertebereich aus vorherigen Werten ist eine Schwachstelle, die auftritt, wenn ein Zufallszahlengenerator Sequenzen erzeugt, die es Angreifern ermöglichen, einen relativ kleinen Bereich von Möglichkeiten für den nächsten Wert basierend auf der Beobachtung vorheriger Ausgaben abzuleiten. Im Gegensatz zur exakten Vorhersage, bei der der nächste Wert präzise berechnet werden kann, beinhaltet diese Schwäche Situationen, in denen der Ausgaberaum durch Musteranalyse eingeschränkt wird. Beispielsweise könnte ein Generator monoton steigende Werte innerhalb eines Bereichs erzeugen, Clustering-Muster aufweisen oder beobachtbare Beziehungen zwischen aufeinanderfolgenden Ausgaben haben, die den Vorhersageraum einengen. Dies reduziert den Brute-Force-Aufwand des Angreifers von der Suche im gesamten Werteraum auf die Suche in einer viel kleineren Teilmenge.
Risiko
Bereichsvorhersagbarkeit reduziert die Sicherheit von Systemen, die auf Zufallswerten basieren, erheblich. Wenn ein Angreifer die Möglichkeiten für Session-Tokens von 2^128 auf 2^16 durch Beobachtung von Mustern einschränken kann, wird Brute-Force machbar. Selbst partielle Vorhersage verbessert die Angriffseffizienz dramatisch - die Reduzierung des Suchraums um einen Faktor von 1000 macht Angriffe 1000-mal schneller. Die Schwachstelle ermöglicht probabilistische Angriffe, bei denen Angreifer zuerst die wahrscheinlichsten Werte ausprobieren. Muster wie monotone Sequenzen, Wert-Clustering oder begrenzte Variationen gegenüber vorherigen Ausgaben liefern alle ausnutzbare Informationen. Das Risiko wird verstärkt, wenn Angreifer viele Vermutungen schnell machen können, wie bei Online-Session-Hijacking-Versuchen. Systeme können scheinbar ausreichende Entropie verwenden, während sie tatsächlich Ausgaben auf vorhersagbare Bereiche beschränken.
Lösung
Verwenden Sie kryptografisch sichere Zufallszahlengeneratoren, die Ausgaben mit gleichmäßiger Verteilung über den gesamten Werteraum unabhängig von vorherigen Ausgaben erzeugen. Jeder generierte Wert sollte statistisch unabhängig von allen vorherigen Werten sein. Vermeiden Sie Generatoren mit Mustern, Verzerrungen oder Ausgabebeziehungen, auch wenn exakte Vorhersage nicht möglich ist. Testen Sie Zufallszahlengeneratoren mit statistischer Analyse, um ungleichmäßige Verteilungen oder Korrelationen zu erkennen. Implementieren Sie ordnungsgemäßes Seeding mit ausreichender Entropie. Verwenden Sie etablierte kryptografische Bibliotheken anstelle von benutzerdefinierten Implementierungen. Führen Sie Sicherheitsanalysen durch, um sicherzustellen, dass generierte Werte keine ausnutzbaren Muster aufweisen.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Umfang: Zugriffskontrolle Angreifer, die den Vorhersagebereich einschränken können, können Authentifizierungs-Tokens, Session-IDs und Zugangsdaten effizienter per Brute-Force knacken. |
| Vertraulichkeit | Umfang: Vertraulichkeit Kryptografische Schlüssel oder Nonces mit vorhersagbaren Bereichen können anfälliger für kryptoanalytische Angriffe sein. |
| Integrität | Umfang: Integrität Transaktions-IDs oder Integritäts-Tokens mit vorhersagbaren Bereichen ermöglichen effizientere Fälschungsangriffe. |
Beispielcode
Anfälliger Code (Python/C)
Die folgenden Beispiele demonstrieren bereichs-vorhersagbare Wertgenerierung:
# Anfällig: Vorhersagbare Wertebereiche
import random
import time
# Anfällig: Monoton steigend mit Grenzen
class VulnerableIncreasing:
def __init__(self):
self.current = random.randint(0, 1000)
def next(self):
# Anfällig: Erhöht sich immer um 1-10
# Bei bekanntem aktuellem Wert ist nächster im Bereich [aktuell+1, aktuell+10]
increment = random.randint(1, 10)
self.current += increment
return self.current
# Anfällig: Begrenzte Variation vom Vorherigen
class VulnerableBoundedVariation:
def __init__(self):
self.previous = random.randint(0, 10000)
def next(self):
# Anfällig: Neuer Wert innerhalb ±100 vom Vorherigen
# Bereich ist vorhersagbar: [vorheriger-100, vorheriger+100]
variation = random.randint(-100, 100)
self.previous = max(0, self.previous + variation)
return self.previous
# Anfällig: Zyklisch mit vorhersagbarer Phase
class VulnerableCyclic:
def __init__(self):
self.counter = 0
def next(self):
self.counter += 1
# Anfällig: Folgt Sinuswellenmuster
# Bereich hängt von Phase ab
import math
base = int(5000 + 4000 * math.sin(self.counter * 0.1))
noise = random.randint(-50, 50)
return base + noise
# Anfällig: Clustering um aktuelle Werte
class VulnerableClustering:
def __init__(self):
self.history = [random.randint(0, 10000) for _ in range(5)]
def next(self):
# Anfällig: Neuer Wert clustert um Durchschnitt
avg = sum(self.history) / len(self.history)
spread = random.randint(-500, 500)
new_value = int(avg + spread)
self.history.pop(0)
self.history.append(new_value)
return new_value
# Anfällig: Verzerrt zu bestimmten Bereichen
class VulnerableBiased:
def next(self):
# Anfällig: 80% der Werte fallen in schmalen Bereich
if random.random() < 0.8:
return random.randint(4000, 6000) # 2000er Bereich
else:
return random.randint(0, 10000) # Vollständiger Bereich
# Anfällig: Zeit-begrenzte Vorhersagen
class VulnerableTimeBounded:
def next(self):
# Anfällig: Wert durch Tageszeit eingeschränkt
hour = time.localtime().tm_hour
# Morgens: 0-3000, Nachmittags: 3000-6000, Abends: 6000-10000
if hour < 12:
return random.randint(0, 3000)
elif hour < 18:
return random.randint(3000, 6000)
else:
return random.randint(6000, 10000)
// Anfällig: Bereichs-vorhersagbare Generierung in C
#include <stdlib.h>
#include <time.h>
#include <math.h>
// Anfällig: Monotone Erhöhung
static unsigned int mono_value = 0;
unsigned int vulnerable_monotonic() {
// Anfällig: Inkrement begrenzt [1, 100]
mono_value += (rand() % 100) + 1;
return mono_value;
}
// Anfällig: Random Walk mit Drift
static int walk_value = 5000;
int vulnerable_random_walk() {
// Anfällig: Begrenzte Schrittgröße
int step = (rand() % 201) - 100; // -100 bis +100
walk_value += step;
// In Grenzen halten
if (walk_value < 0) walk_value = 0;
if (walk_value > 10000) walk_value = 10000;
return walk_value;
}
// Anfällig: Oszillierendes Muster
static int phase = 0;
unsigned int vulnerable_oscillating() {
phase++;
// Anfällig: Folgt vorhersagbarer Oszillation
int base = 5000 + (int)(4000 * sin(phase * 0.05));
int noise = rand() % 100 - 50;
return base + noise;
}
// Anfällig: Quantisierte Ausgabe
unsigned int vulnerable_quantized() {
unsigned int raw = rand();
// Anfällig: Ausgabe immer Vielfaches von 1000
// Nur 10 mögliche Werte: 0, 1000, 2000, ..., 9000
return (raw % 10) * 1000;
}
// Anfällig: Verzerrte Verteilung
unsigned int vulnerable_biased() {
int r = rand() % 100;
// Anfällig: Die meisten Werte in schmalem Band
if (r < 70) {
return 4500 + (rand() % 1000); // 4500-5500 (70%)
} else if (r < 90) {
return 3000 + (rand() % 1500); // 3000-4500 (20%)
} else {
return rand() % 10000; // Vollständiger Bereich (10%)
}
}
// Anfällig: Vorherigen-abhängige Grenzen
static unsigned int prev_value = 5000;
unsigned int vulnerable_dependent_bounds() {
// Anfällig: Bereich hängt vom vorherigen Wert ab
unsigned int low = prev_value > 1000 ? prev_value - 1000 : 0;
unsigned int high = prev_value + 1000;
if (high > 10000) high = 10000;
prev_value = low + (rand() % (high - low + 1));
return prev_value;
}
Korrigierter Code (Python/C)
# Korrigiert: Unvorhersagbare Generierung über vollständigen Bereich
import secrets
import os
# Korrigiert: Vollständiger Bereich mit gleichmäßiger Verteilung
class SecureUniform:
@staticmethod
def next(max_value=10000):
# Korrigiert: Jeder Wert unabhängig, vollständiger Bereich möglich
return secrets.randbelow(max_value)
# Korrigiert: Kein Muster zwischen aufeinanderfolgenden Werten
class SecureIndependent:
@staticmethod
def next():
# Korrigiert: 64-Bit zufällig, keine Beziehung zum Vorherigen
return secrets.randbits(64)
# Korrigiert: Sicher wenn monoton für Sortierung benötigt
class SecureMonotonic:
def __init__(self):
self.counter = 0
self.random_base = secrets.randbits(64)
def next(self):
self.counter += 1
# Korrigiert: Zufallskomponente verhindert Bereichsvorhersage
random_part = secrets.randbits(32)
return (self.random_base + self.counter) ^ random_part
# Korrigiert: Kein Clustering
class SecureNoClustering:
@staticmethod
def next():
# Korrigiert: Jeder Wert unabhängig von Historie
return secrets.token_hex(16)
# Korrigiert: Gleichmäßige Verteilung
class SecureUnbiased:
@staticmethod
def next(max_value=10000):
# Korrigiert: secrets.randbelow ist gleichmäßig verteilt
return secrets.randbelow(max_value)
# Korrigiert: Zeit-unabhängig
class SecureTimeIndependent:
@staticmethod
def next():
# Korrigiert: Keine Zeit-Abhängigkeit in Ausgabe
return secrets.randbits(64)
# Korrigiert: Vollständiges Entropie-Byte-Array
class SecureBytes:
@staticmethod
def next(length=16):
# Korrigiert: Jedes Byte unabhängig, vollständiger Bereich 0-255
return os.urandom(length)
// Korrigiert: Unvorhersagbare Generierung über vollständigen Bereich in C
#include <openssl/rand.h>
#include <stdio.h>
// Korrigiert: Vollständiger Bereich zufällig
int secure_random(unsigned int *value, unsigned int max) {
unsigned int random_value;
if (RAND_bytes((unsigned char*)&random_value, sizeof(random_value)) != 1) {
return -1;
}
// Korrigiert: Gleichmäßige Verteilung in [0, max)
*value = random_value % max;
return 0;
}
// Korrigiert: Unabhängig von vorherigen Werten
int secure_independent(unsigned char *buffer, size_t len) {
// Korrigiert: Jedes Byte unabhängig, vollständiger 0-255 Bereich
return RAND_bytes(buffer, len) == 1 ? 0 : -1;
}
// Korrigiert: Sichere Monotonie wenn Sortierung erforderlich
typedef struct {
unsigned long long counter;
unsigned char key[32];
} SecureMonotonic;
int secure_monotonic_init(SecureMonotonic *sm) {
if (RAND_bytes(sm->key, sizeof(sm->key)) != 1) {
return -1;
}
sm->counter = 0;
return 0;
}
int secure_monotonic_next(SecureMonotonic *sm, unsigned char *output) {
sm->counter++;
// Korrigiert: HMAC stellt Unvorhersagbarkeit der Ausgabe sicher
unsigned char input[8];
for (int i = 0; i < 8; i++) {
input[i] = (sm->counter >> (56 - i*8)) & 0xFF;
}
// HMAC-SHA256 zur Ausgabegenerierung verwenden
// (vereinfacht - tatsächliche Implementierung würde OpenSSL HMAC verwenden)
return RAND_bytes(output, 32);
}
// Korrigiert: Keine Verzerrung
int secure_unbiased(unsigned int *value, unsigned int max) {
unsigned int random_value;
unsigned int threshold = (UINT_MAX - (UINT_MAX % max)) % max;
// Korrigiert: Rejection Sampling für unverzerrtes Ergebnis
do {
if (RAND_bytes((unsigned char*)&random_value, sizeof(random_value)) != 1) {
return -1;
}
} while (random_value < threshold);
*value = random_value % max;
return 0;
}
// Korrigiert: Volle Entropie-Ausgabe
int secure_full_entropy(unsigned char *buffer, size_t len) {
// Korrigiert: Jedes Byte hat volle 8 Bits Entropie
return RAND_bytes(buffer, len) == 1 ? 0 : -1;
}
Die Korrektur stellt sicher, dass jeder Wert statistisch unabhängig mit gleichmäßiger Verteilung über den gesamten Werteraum ist.
Ausgenutzt in der Praxis
Statistische Analyse-Angriffe
Verschiedene Systeme, die verzerrte oder bereichs-limitierte Zufallszahlengeneratoren verwenden, wurden durch statistische Analyse ausgenutzt, die vorhersagbare Muster aufdeckte.
Session-Token Bereichsanalyse
Webanwendungen mit geclusterten Session-Token-Verteilungen wurden angegriffen, indem Vermutungen auf wahrscheinliche Wertebereiche konzentriert wurden.
Tools zum Testen/Ausnutzen
-
ENT — Statistische Analyse von Zufälligkeit.
-
NIST Statistical Test Suite — Tests für Zufallszahlenqualität.
-
Benutzerdefinierte Analyse-Skripte — Erkennt Muster und Bereichseinschränkungen.
CVE-Beispiele
Keine spezifischen CVEs referenzieren direkt dieses CWE, aber die zugrundeliegenden Muster erscheinen in vielen Schwachstellen, die schwache Zufallszahlengeneratoren beinhalten.
Referenzen
-
MITRE Corporation. "CWE-343: Predictable Value Range from Previous Values." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/343.html
-
NIST. "A Statistical Test Suite for Random and Pseudorandom Number Generators." SP 800-22. https://csrc.nist.gov/publications/detail/sp/800-22/rev-1a/final
-
Goldberg, I., Wagner, D. "Randomness and the Netscape Browser." Dr. Dobb's Journal, 1996.