FlawOpen

flawopen.com/Unsichere Deserialisierung/PHP unserialize()

Ist PHP unserialize() für nicht vertrauenswürdige Eingaben sicher?

CWE-502: Deserialization of Untrusted DataReferenzseite
Kurzantwort

Übergib keine nicht vertrauenswürdigen Daten an unserialize(), auch nicht mit allowed_classes. PHP kann Objekte wiederherstellen und __unserialize() oder __wakeup() aufrufen; Angreifer könnten verfügbare Anwendungs- oder Autoloader-Klassen ausnutzen. Verwende JSON für nicht vertrauenswürdige Daten. Bei assoziativer Dekodierung werden JSON-Objekte zu Arrays und instanziieren keine Anwendungsklassen mit Magic-Method-Verhalten.

VERWUNDBAR
<?php
// Cookie content is controlled by the client.
$input = $_COOKIE['prefs'] ?? '';
$data = unserialize($input);

// Restoring an object may invoke its
// __unserialize() or __wakeup() method.
// Later object destruction may invoke __destruct().

// The risk depends on available classes,
// their serialized state, and reachable behavior.
BEHOBEN
<?php
$input = $_POST['prefs'] ?? null;
if (!is_string($input)) {
    http_response_code(400);
    exit;
}

try {
    $data = json_decode(
        $input,
        true,
        512,
        JSON_THROW_ON_ERROR
    );
} catch (JsonException $e) {
    http_response_code(400);
    exit;
}

if (!is_array($data)) {
    http_response_code(400);
    exit;
}

// Validate required keys and value types here.

Was eine PHP-Objektinjektionskette voraussetzt

Objektinjektion bedeutet nicht automatisch Codeausführung. Der serialisierte Wert muss eine von PHP auflösbare und laut Optionen erlaubte Klasse benennen; Wiederherstellung oder spätere Nutzung muss außerdem Verhalten mit Sicherheitsauswirkung erreichen. PHP kann beim Wiederherstellen __unserialize() oder __wakeup() aufrufen; __destruct() kann bei der Zerstörung laufen und __toString() nur in einem String-Kontext.

Eine Property-Oriented-Programming-Kette (POP) verbindet Verhalten, das bereits in der Anwendung oder geladenen Abhängigkeiten vorhanden ist. Die Ausnutzbarkeit hängt von realen Klassen, serialisierten Eigenschaften, Aufrufpfad und Laufzeitbedingungen ab. Eine Gadget-Kette für das Ziel muss nachgewiesen werden; unserialize() allein belegt sie nicht.

Warum Stringfilter und allowed_classes keine vollständige Lösung sind

Das Sperren eines Markers wie O:, das Filtern von Klassennamen oder eine Längenbegrenzung validiert PHP-Serialisierung nicht sicher. PHP warnt ausdrücklich davor, nicht vertrauenswürdige Eingaben an unserialize() zu übergeben, unabhängig von allowed_classes. Nicht erlaubte Klassen werden zu __PHP_Incomplete_Class; die Struktur wird trotzdem geparst. Validiere bei vertrauenswürdigen Altdaten die Ergebnisform und begrenze die Tiefe. Nutze für Clientzustand JSON.

Häufige Fragen

Macht allowed_classes => false nicht vertrauenswürdige Daten sicher?

Nein. Die Option verhindert die normale Wiederherstellung von Anwendungsklassen; nicht erlaubte Objekte werden zu __PHP_Incomplete_Class. PHP warnt weiterhin vor nicht vertrauenswürdigen Daten für unserialize(), auch mit dieser Option. Nutze sie nur als Defense-in-Depth für vertrauenswürdige Altdaten, validiere das Ergebnis und begrenze max_depth. Laut PHP-Handbuch wirkt die Option nicht auf Enumerationen.

Macht ein HMAC serialisierte Daten sicher?

Er kann Datenintegrität für von deiner Anwendung erzeugte Daten bestätigen, wenn der Schlüssel geheim bleibt und hash_equals() die Signatur vor dem Deserialisieren prüft. Ungültige Signaturen müssen vor dem Parsen abgelehnt werden. Ein HMAC verschlüsselt nicht und verhindert keine Wiederholung; ergänze Ablaufzeit oder Nonce, wenn Aktualität nötig ist. Signiere keine beliebigen Nutzerdaten, um sie vertrauenswürdig zu machen.

Ist das dasselbe Risiko wie bei Python pickle oder Java ObjectInputStream?

Alle bergen das allgemeine Risiko, Objekte aus serialisierten Daten wiederherzustellen. Formate, Hooks, Klassenauflösung und Gegenmaßnahmen unterscheiden sich jedoch. Bewerte Runtime und verfügbare Klassen jeweils separat; eine Gadget-Kette einer Plattform gilt nicht automatisch für andere.

Quellen

Siehe auch Unsichere Deserialisierung: Risiken und Schutz Python pickle.load(): Risiken nicht vertrauenswürdiger Daten Ist Ruby YAML.load sicher? Psych-Versionen und safe_load .NET BinaryFormatter: Risiken und Migration Java ObjectInputStream: Deserialisierung sicher gestalten Newtonsoft.Json TypeNameHandling: sichere Konfiguration?