flawopen.com/Unsichere Deserialisierung/Python-pickle-Sicherheit
Ist pickle.load() bei nicht vertrauenswürdigen Daten sicher?
Nein. Behandle pickle wie ein Programm in einem Paket, nicht wie einen passiven Datensatz: Beim Laden kann Rekonstruktionsverhalten ausgeführt werden, bevor die Anwendung das Objekt prüft. Verwende für Eingaben über Vertrauensgrenzen ein reines Datenformat.
import pickle # Never accept pickle bytes from a request, upload, # shared cache, or other untrusted source. obj = pickle.loads(untrusted_bytes)
import json
def parse_profile(raw: bytes) -> dict[str, str]:
if len(raw) > 65_536:
raise ValueError("Payload too large")
try:
value = json.loads(raw)
except (json.JSONDecodeError, UnicodeDecodeError):
raise ValueError("Invalid JSON") from None
if not isinstance(value, dict) or set(value) - {"display_name", "theme"}:
raise ValueError("Invalid profile")
name = value.get("display_name")
theme = value.get("theme")
if not isinstance(name, str) or len(name) > 80:
raise ValueError("Invalid display name")
if theme not in {"light", "dark"}:
raise ValueError("Invalid theme")
return {"display_name": name, "theme": theme}
- Pickle-Stream:
- Python-spezifische Bytefolge zur Objektrekonstruktion, einschließlich globaler Referenzen und Rekonstruktionsverhalten.
- Unpickling:
- Interpretieren des Streams und Wiederherstellen des Objektgraphen; dabei können Funktionen aufgerufen werden.
- Vertrauensgrenze:
- Stelle, an der Nutzer, Dienst, Upload oder gemeinsamer Speicher Bytes kontrollieren oder ändern kann.
- CWE-502:
- Deserialisierung nicht vertrauenswürdiger Daten; die Auswirkung hängt davon ab, ob Angreifer geladene Daten liefern oder verändern können.
Nicht vertrauenswürdige Bytes erreichen pickle
Upload, Anfrage, Cache oder Artefakt kann vom Angreifer kontrollierte oder veränderte Pickle-Daten in den Prozess bringen.
Der Unpickler löst Globals auf
Der Interpreter verarbeitet Rekonstruktionsanweisungen; find_class() kann benannte Globals einschließlich Funktionen importieren und zurückgeben.
Das Laden löst Verhalten aus
Anweisungen können während load() oder loads() Funktionen aufrufen, bevor die Anwendung das Ergebnis prüft.
Die Auswirkung folgt den Prozessrechten
Das Verhalten läuft mit den Rechten des Python-Prozesses. Netzwerk, Geheimnisse, Dateizugriff und Isolation begrenzen den Schaden.
Warum das Laden von pickle eine Codeausführungsgrenze überschreitet
Ein Pickle-Stream kann Globals und Rekonstruktionsfunktionen benennen. Beim Unpickling löst Unpickler.find_class() Globals einschließlich Funktionen auf; Opcodes können Rekonstruktion auslösen. Gefährlich ist bereits pickle.load() oder pickle.loads(); ein späterer separater execute-Aufruf ist nicht nötig. Der resultierende Code hat die Rechte des Prozesses. Das ist dokumentiertes Formatverhalten; nutze pickle nicht für den Austausch nicht vertrauenswürdiger Daten.
Was JSON behebt — und was nicht
Python warnt, dass das Laden nicht vertrauenswürdiger oder manipulierter Pickle-Daten Code ausführen kann; JSON-Decodierung erzeugt diesen Codeausführungspfad nicht von selbst. JSON validiert Eingaben nicht automatisch: Begrenze die Größe, fordere erwarteten Typ und Felder, prüfe Werte anhand eines Schemas und wende Autorisierung separat an. Muss ein Altprozess pickle laden, authentifiziere vorab die exakten Bytes mit einem geschützten Schlüssel. Eine Signatur belegt Herkunft und Integrität nur unter den Schlüsselannahmen und macht bösartige Daten eines vertrauenswürdigen Signierers nicht sicher. Migriere zu einem Datenformat.
- ✓Entferne
pickle.load()undpickle.loads()aus Pfaden für Anfragen, Uploads, gemeinsame Caches und Artefakte unklarer Herkunft. - ✓Nutze JSON oder ein Datenformat und erzwinge Größenlimit, Schema, erlaubte Felder, Wertebereiche und Endpoint-Autorisierung.
- ✓Wenn ein vertrauenswürdiger interner Ablauf pickle vorübergehend behält, prüfe HMAC oder Signatur der exakten Bytes vor dem Laden, schütze den Schlüssel und beschränke Prozessrechte.
- ✓Suche Pickle-Verbraucher im Code und Datenfluss; ermittle, wer jede Quelle ändern kann, und migriere oder isoliere riskante Stellen.
Häufige Fragen
Eine Überschreibung von find_class() kann Globals einschränken, aber einen Loader für alle Protokolle und erreichbaren Verhaltensweisen als sicher zu beweisen ist schwierig. Für nutzerkontrollierte Bytes ist ein Datenformat vorzuziehen.
Ja. JSON vermeidet pickle-artige Codeausführung beim Decodieren, doch Typen, Felder, Größe, Werte und Berechtigungen müssen geprüft werden. Trenne JSON-Parsing von Geschäftsregeln.
Primärquellen
- Python-Dokumentation — Pickle-Sicherheitswarnung und eingeschränkte Globals
- Python-Dokumentation — JSON-Decoder
- CWE-502 — Deserialisierung nicht vertrauenswürdiger Daten