Deserialisierung nicht vertrauenswürdiger Daten
Beschreibung
Deserialisierung nicht vertrauenswürdiger Daten tritt auf, wenn eine Anwendung Daten aus einer nicht vertrauenswürdigen Quelle deserialisiert, ohne ausreichend zu überprüfen, dass die resultierenden Daten gültig und sicher sind. Serialisierung konvertiert Objekte in ein Format zur Speicherung oder Übertragung; Deserialisierung rekonstruiert Objekte aus diesem Format. Wenn Angreifer serialisierte Daten kontrollieren, können sie diese manipulieren, um beliebige Objekte zu instanziieren, bösartige Eigenschaftswerte zu setzen oder gefährliche Operationen während des Deserialisierungsprozesses auszulösen. Dies führt häufig zu Remote Code Execution, da viele Programmiersprachen es Objekten erlauben, Code während der Deserialisierung auszuführen.
Risiko
Deserialisierungs-Schwachstellen gehören zu den schwerwiegendsten und ermöglichen konsistent Remote Code Execution ohne erforderliche Authentifizierung. Java-, PHP-, Python- (pickle), .NET- und Ruby-Anwendungen sind häufig betroffen. Der Equifax-Breach 2017 nutzte Apache Struts Deserialisierung aus. Jüngste Schwachstellen in NVIDIA NeMo Framework und LangChain LangGraph demonstrieren das anhaltende Risiko in AI/ML-Systemen. Angreifer erstellen bösartige serialisierte Payloads (oft "Gadget Chains" genannt), die bei der Deserialisierung Code-Ausführung auslösen. Die Auswirkung ist typischerweise vollständige Systemkompromittierung mit den Privilegien der Anwendung.
Lösung
Vermeiden Sie nach Möglichkeit die Deserialisierung von Daten aus nicht vertrauenswürdigen Quellen. Verwenden Sie textbasierte Formate wie JSON oder YAML anstelle von binärer Serialisierung für Datenaustausch. Implementieren Sie Integritätsprüfungen (HMAC, digitale Signaturen) für serialisierte Daten. Verwenden Sie Allowlists, um einzuschränken, welche Klassen deserialisiert werden können. In Java überschreiben Sie ObjectInputStream.resolveClass() oder verwenden Sie Bibliotheken wie SerialKiller. In Python verwenden Sie niemals pickle mit nicht vertrauenswürdigen Daten - verwenden Sie stattdessen JSON. Isolieren Sie Deserialisierung in Sandbox-Umgebungen. Überwachen Sie Logs auf deserialisierungsbezogene Exceptions.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle | Bereich: Remote Code Execution Angreifer führen beliebigen Code aus, indem sie bösartige serialisierte Objekte erstellen, die während der Deserialisierung Code auslösen. |
| Integrität | Bereich: Datenmanipulation Manipulierte serialisierte Objekte verändern den Anwendungszustand und Daten. |
| Verfügbarkeit | Bereich: Denial of Service Bösartige Payloads können übermäßige Ressourcen verbrauchen oder die Anwendung zum Absturz bringen. |
Beispielcode
Verwundbarer Code
// VERWUNDBAR: Deserialisierung nicht vertrauenswürdiger Daten
import java.io.*;
public class UserService {
public User loadUser(byte[] data) throws Exception {
// Deserialisierung benutzerkontrollierter Daten - RCE möglich!
ObjectInputStream ois = new ObjectInputStream(
new ByteArrayInputStream(data));
return (User) ois.readObject(); // Führt Gadget Chain aus
}
}
// Angreifer sendet serialisierten Payload mit bösartiger Gadget Chain
// Beispiel: ysoserial CommonsCollections Payload
# VERWUNDBAR: Verwendung von pickle mit nicht vertrauenswürdigen Daten
import pickle
def load_user_session(session_data):
# NIEMALS pickle mit nicht vertrauenswürdigen Daten verwenden!
return pickle.loads(session_data) # RCE möglich
# Angreifer-Payload:
# import pickle, os
# class Exploit:
# def __reduce__(self):
# return (os.system, ('rm -rf /',))
# pickle.dumps(Exploit())
// VERWUNDBAR: Deserialisierung von Benutzereingabe
<?php
$data = $_COOKIE['user_data'];
$user = unserialize($data); // Object Injection!
// Angreifer kann jede Klasse mit kontrollierten Eigenschaften instanziieren
// Wenn eine __destruct oder __wakeup Methode Nebeneffekte hat, ist RCE möglich
?>
Lösungscode
// SICHER: JSON statt Java-Serialisierung verwenden
import com.fasterxml.jackson.databind.ObjectMapper;
public class UserService {
private static final ObjectMapper mapper = new ObjectMapper();
public User loadUser(String jsonData) throws Exception {
// JSON-Parsing - keine Code-Ausführung
return mapper.readValue(jsonData, User.class);
}
}
// SICHER: Eingeschränkte Deserialisierung mit Allowlist
import java.io.*;
import java.util.Set;
public class SafeObjectInputStream extends ObjectInputStream {
private static final Set<String> ALLOWED_CLASSES = Set.of(
"com.example.User",
"com.example.Address",
"java.lang.String"
);
public SafeObjectInputStream(InputStream in) throws IOException {
super(in);
}
@Override
protected Class<?> resolveClass(ObjectStreamClass desc)
throws IOException, ClassNotFoundException {
if (!ALLOWED_CLASSES.contains(desc.getName())) {
throw new InvalidClassException("Nicht autorisierte Klasse: " + desc.getName());
}
return super.resolveClass(desc);
}
}
# SICHER: JSON statt pickle verwenden
import json
def load_user_session_safe(session_data):
# JSON ist sicher - keine Code-Ausführung beim Parsen
data = json.loads(session_data)
return User(**data)
# SICHER: Wenn pickle absolut erforderlich ist, HMAC-Verifizierung verwenden
import pickle
import hmac
import hashlib
SECRET_KEY = b'your-secret-key'
def secure_pickle_dumps(obj):
data = pickle.dumps(obj)
signature = hmac.new(SECRET_KEY, data, hashlib.sha256).digest()
return signature + data
def secure_pickle_loads(signed_data):
signature = signed_data[:32]
data = signed_data[32:]
expected_sig = hmac.new(SECRET_KEY, data, hashlib.sha256).digest()
if not hmac.compare_digest(signature, expected_sig):
raise ValueError("Ungültige Signatur - Daten manipuliert")
return pickle.loads(data) # Nur verifizierte Daten deserialisieren
// SICHER: JSON statt serialize verwenden
<?php
$data = $_COOKIE['user_data'];
$user_array = json_decode($data, true); // Gibt Array zurück, kein Objekt
// Daten validieren
if (!isset($user_array['id']) || !is_int($user_array['id'])) {
throw new Exception("Ungültige Benutzerdaten");
}
$user = new User($user_array['id'], $user_array['name']);
// SICHER: Wenn unserialize erforderlich ist, allowed_classes verwenden
$user = unserialize($data, ['allowed_classes' => ['User', 'Address']]);
?>
Ausgenutzt in der Praxis
Apache Struts / Equifax-Breach (Apache, 2017)
CVE-2017-5638 betraf Apache Struts bei der Deserialisierung nicht vertrauenswürdiger Daten, was zum Equifax-Breach führte, bei dem 147 Millionen Datensätze offengelegt wurden. Dies demonstrierte das katastrophale Potenzial von Deserialisierungs-Schwachstellen.
NVIDIA NeMo Framework (NVIDIA, 2025)
CVE-2025-23249 im NVIDIA NeMo Framework ermöglicht Remote Code Execution durch manipulierte serialisierte Daten und betrifft AI/ML-Entwicklungs-Pipelines in Technologie-, Automobil-, Finanz- und Gesundheitssektoren.
LangChain LangGraph (LangChain, 2025)
CVE-2025-64439 in LangGraph ermöglicht RCE, wenn msgpack-Serialisierung fehlschlägt und auf den verwundbaren JSON-Modus zurückfällt, was AI-Agent-Frameworks betrifft.
Tools zum Testen/Ausnutzen
-
ysoserial — Java-Deserialisierungs-Payload-Generator.
-
phpggc — PHP-Gadget-Chain-Generator.
-
Burp Suite Deserialization Scanner — Erkennung von Deserialisierungsproblemen.
CVE-Beispiele
-
CVE-2017-5638 — Apache Struts RCE (Equifax-Breach).
-
CVE-2025-23249 — NVIDIA NeMo Deserialisierungs-RCE.
-
CVE-2015-4852 — WebLogic Commons Collections Deserialisierung.
Referenzen
-
MITRE. "CWE-502: Deserialization of Untrusted Data." https://cwe.mitre.org/data/definitions/502.html
-
OWASP. "Deserialization of Untrusted Data." https://owasp.org/www-community/vulnerabilities/Deserialization_of_untrusted_data