Sicherheitsrisiken bei der Verwendung von Pickle zur Deserialisierung in Python
Wenhao Wang
Dev Intern · Leapcell

Deserialisierungsangriffe und Verhinderung des Pickle-Moduls in Python
Einführung
Hallo zusammen! Im Bereich der Python-Programmierung gibt es ein potenzielles Sicherheitsrisiko – Deserialisierungsangriffe. Bevor wir uns mit Deserialisierungsangriffen befassen, ist es wichtig, dass wir verstehen, was Serialisierung und Deserialisierung sind.
Konzeptionell ist die Serialisierung der Prozess der Umwandlung einer Datenstruktur oder eines Objekts in einen Byte-Stream. Durch diese Konvertierung können Daten bequem in einer Datei gespeichert oder über ein Netzwerk übertragen werden. Deserialisierung hingegen ist der umgekehrte Prozess, der den Byte-Stream zurück in die ursprüngliche Datenstruktur oder das ursprüngliche Objekt umwandelt.
In Python ist das Pickle-Modul eines der am häufigsten verwendeten Werkzeuge zur Implementierung von Serialisierung und Deserialisierung. Es bietet eine bequeme Schnittstelle, die komplexe Python-Objekte serialisieren und speichern kann, und bei Bedarf später einfach deserialisieren und wiederherstellen kann. Diese Bequemlichkeit birgt jedoch auch potenzielle Sicherheitsrisiken.
Überblick über Deserialisierungsangriffe
Der Deserialisierungsprozess ist nicht immer sicher und zuverlässig. Wenn wir Deserialisierungsoperationen aus einer nicht vertrauenswürdigen Datenquelle durchführen, besteht die Möglichkeit, dass wir unter Deserialisierungsangriffen leiden. Angreifer können bösartigen Code in die serialisierten Daten einbetten. Sobald diese Daten deserialisiert werden, wird der eingebettete bösartige Code ausgeführt. Solche Angriffe können zu schwerwiegenden Folgen führen, wie z. B. Datenlecks, Systemabstürzen und ermöglichen es Angreifern sogar, Remote-Kontrollberechtigungen des Systems zu erhalten.
Überblick über das Python Pickle-Modul
Grundlegende Funktionen von Pickle
Das Pickle-Modul ist Teil der Python-Standardbibliothek und kann ohne zusätzliche Installation verwendet werden. Seine Hauptfunktion besteht darin, die Serialisierung und Deserialisierung von Python-Objekten zu implementieren. Ob es sich um einen einfachen grundlegenden Datentyp oder eine komplexe Datenstruktur handelt (z. B. Listen, Dictionaries, Klasseninstanzen usw.), Pickle kann ihn in einen Byte-Stream zur Speicherung oder Übertragung konvertieren und bei Bedarf in die ursprüngliche Objektform zurückversetzen.
Funktionsprinzip von Pickle
Das Funktionsprinzip von Pickle ist relativ intuitiv. In der Serialisierungsphase konvertiert es Python-Objekte nach bestimmten Regeln in Byte-Streams. Diese Byte-Streams enthalten die Typinformationen und den Dateninhalt der Objekte. In der Deserialisierungsphase liest Pickle den Byte-Stream und stellt ihn gemäß den darin enthaltenen Informationen in das entsprechende Python-Objekt wieder her.
Serialisierung und Deserialisierung von Pickle
- Serialisierung:
Pickle bietet zwei Hauptserialisierungsfunktionen:
pickle.dump
undpickle.dumps
. Die Funktionpickle.dump
schreibt das serialisierte Objekt direkt in die angegebene Datei, während die Funktionpickle.dumps
einen Byte-Stream zurückgibt, der die serialisierten Daten enthält.
import pickle # Objekt erstellen data = {'name': 'Leapcell', 'age': 29, 'city': 'New York'} # Serialisieren Sie das Objekt und schreiben Sie es in eine Datei. with open('data.pickle', 'wb') as file: pickle.dump(data, file) # Oder einen Byte-Stream zurückgeben data_bytes = pickle.dumps(data)
- Deserialisierung:
Es gibt auch zwei häufig verwendete Funktionen für die Deserialisierung:
pickle.load
undpickle.loads
. Die Funktionpickle.load
liest den Byte-Stream aus der angegebenen Datei und deserialisiert ihn, und die Funktionpickle.loads
deserialisiert direkt einen Byte-Stream.
import pickle # Deserialisieren Sie das Objekt aus der Datei. with open('data.pickle', 'rb') as file: data = pickle.load(file) # Oder einen Byte-Stream direkt deserialisieren data = pickle.loads(data_bytes)
Prinzip der Deserialisierungsangriffe
Angriffsmechanismus
Der Kern von Deserialisierungsangriffen besteht darin, dass Angreifer bösartigen Code in die serialisierten Daten einschleusen können. Wenn das Zielsystem diese serialisierten Daten, die bösartigen Code enthalten, deserialisiert, wird der bösartige Code ausgeführt, wodurch das Ziel des Angreifers erreicht wird. Das heißt, wenn wir während der Deserialisierung keine strenge Überprüfung und Durchmusterung der Datenquelle durchführen, ist es gleichbedeutend damit, Angreifern die Tür zu öffnen, um beliebigen Code im System auszuführen.
Was Angreifer tun können
Angreifer können Deserialisierungslücken nutzen, um eine Vielzahl bösartiger Operationen durchzuführen, wie z. B. das Ausführen beliebiger Systembefehle, das Ändern wichtiger Daten im System oder das Stehlen vertraulicher Informationen usw. Diese Operationen können die Sicherheit und Stabilität des Systems ernsthaft beeinträchtigen.
Beispielcode
Um den Prozess von Deserialisierungsangriffen klarer zu veranschaulichen, sehen wir uns ein konkretes Beispiel an:
import pickle import os # Bösartigen Code erstellen class Malicious: def __reduce__(self): return (os.system, ('echo Hacked!',)) # Das bösartige Objekt serialisieren malicious_data = pickle.dumps(Malicious()) # Während der Deserialisierung bösartigen Code ausführen pickle.loads(malicious_data)
In diesem Beispiel:
- Bösartigen Code erstellen: Wir definieren eine Klasse namens
Malicious
und geben den Befehlos.system('echo Hacked!')
an, der in ihrer Methode__reduce__
ausgeführt werden soll. Die Methode__reduce__
ist eine spezielle Methode, die Pickle während des Deserialisierungsprozesses aufruft, um das Objekt zu rekonstruieren. - Das bösartige Objekt serialisieren: Verwenden Sie die Funktion
pickle.dumps
, um eine Instanz der KlasseMalicious
zu serialisieren, um den Byte-Streammalicious_data
zu erhalten, der bösartigen Code enthält. - Das bösartige Objekt deserialisieren: Wenn die Funktion
pickle.loads
zum Deserialisieren vonmalicious_data
verwendet wird, wird die Methode__reduce__
aufgerufen, wodurch der angegebene Befehl ausgeführt und "Hacked!" ausgegeben wird.
So verhindern Sie Pickle-Deserialisierungsangriffe
Prinzipien der sicheren Deserialisierung
Das Hauptprinzip zur Verhinderung von Deserialisierungsangriffen besteht darin, Deserialisierungsoperationen aus nicht vertrauenswürdigen Quellen zu vermeiden. Nur wenn die Datenquelle vollständig vertrauenswürdig ist, können Deserialisierungsoperationen durchgeführt werden.
Praktische Verteidigungsmethoden
- Beispiel für sicheren Deserialisierungscode:
Wenn die Deserialisierung mit Pickle in einigen Fällen erforderlich ist, können die Typen von Objekten, die deserialisiert werden können, durch Überladen der Methode
find_class
eingeschränkt werden, wodurch der Umfang der Deserialisierung eingeschränkt wird.
import pickle import types import io # Benutzerdefinierter Unpickler zur Beschränkung deserialisierbarer Typen class RestrictedUnpickler(pickle.Unpickler): def find_class(self, module, name): if module == "builtins" and name in {"str", "list", "dict", "set", "int", "float", "bool"}: return getattr(__import__(module), name) raise pickle.UnpicklingError(f"global '{module}.{name}' ist verboten") def restricted_loads(s): return RestrictedUnpickler(io.BytesIO(s)).load()
Im obigen Code haben wir eine RestrictedUnpickler
-Klasse angepasst, die von pickle.Unpickler
erbt und die Methode find_class
überschreibt. Auf diese Weise dürfen nur einige sichere integrierte Typen deserialisiert werden, wodurch die Sicherheit von Deserialisierungsoperationen verbessert wird.
2. Verwenden Sie andere sichere Serialisierungsmodule (z. B. JSON):
Eine sicherere Option ist die Verwendung des JSON-Moduls anstelle von Pickle für Serialisierungs- und Deserialisierungsoperationen. JSON unterstützt nur grundlegende Datentypen (wie Zeichenfolgen, Zahlen, boolesche Werte, Arrays und Objekte) und führt keinen beliebigen Code aus, daher hat es gewisse Vorteile in Bezug auf die Sicherheit.
import json # Objekt serialisieren data = {'name': 'Leapcell', 'age': 29, 'city': 'New York'} data_json = json.dumps(data) # Objekt deserialisieren data = json.loads(data_json)
Schlussfolgerung
Dieser Artikel stellt umfassend die Konzepte der Serialisierung und Deserialisierung in Python sowie die Anwendung des Pickle-Moduls in diesem Prozess vor. Gleichzeitig werden die Prinzipien von Deserialisierungsangriffen ausführlich erläutert und die Methoden demonstriert, die Angreifer möglicherweise anhand konkreter Codebeispiele anwenden. Abschließend haben wir die Prinzipien und spezifischen Methoden zur Verhinderung von Pickle-Deserialisierungsangriffen erörtert, einschließlich der Einschränkung von Deserialisierungstypen und der Verwendung sichererer Serialisierungsmodule. Es ist zu hoffen, dass durch die Einführung dieses Artikels jeder ein tieferes Verständnis von Deserialisierungsangriffen erlangen und in der tatsächlichen Programmierung wirksame Präventivmaßnahmen ergreifen kann, um die Sicherheit des Systems zu gewährleisten. Wenn Sie Fragen oder Anregungen zum Inhalt dieses Artikels haben, können Sie diese gerne im Kommentarbereich diskutieren.
Leapcell: Das Beste von Serverlosem Webhosting
Schließlich möchte ich eine Plattform empfehlen, die sich am besten für die Bereitstellung von Python-Diensten eignet: Leapcell
🚀 Mit Ihrer Lieblingssprache entwickeln
Mühelos entwickeln in JavaScript, Python, Go oder Rust.
🌍 Unbegrenzte Projekte kostenlos bereitstellen
Zahlen Sie nur für das, was Sie verbrauchen – keine Anfragen, keine Gebühren.
⚡ Pay-as-You-Go, keine versteckten Kosten
Keine Leerlaufgebühren, nur nahtlose Skalierbarkeit.
📖 Entdecken Sie unsere Dokumentation
🔹 Folgen Sie uns auf Twitter: @LeapcellHQ