Sicherheitsaspekte von Pillow: open(), verify() und load()
Das Hochladen von Bildern bedeutet nicht einfach, eine Bilddatei zu empfangen – es geht darum, externe Eingaben an einen Decoder (Parser) weiterzuleiten. Deshalb sind die drei Pillow‑Methoden nicht nur funktionale Beschreibungen, sondern vor allem entscheidend, wann sie aufgerufen werden (also wann die Angriffsfläche geöffnet wird).
open() ist keine „Pixel‑Lade‑Funktion“
Image.open() arbeitet lazy(verzögert). Das bedeutet, die Datei wird lediglich geöffnet und identifiziert, Pixel‑Daten werden noch nicht gelesen. Der Datei-handle kann dabei offen bleiben.
In der Praxis ist die sichere Verwendung von open() sehr einfach:
- Mit
open()Format, Breite/Größe und andere leichte Informationen ermitteln - Durch Richtlinien blockieren: erlaubte Formate, maximale Auflösung/Pixelzahl, Upload‑Größenbeschränkung
- Danach die eigentliche Validierung/Decodierung durchführen
Kurz gesagt: open() dient als Werkzeug, um vor der Decodierung prüfbare Informationen zu extrahieren.
Was garantiert verify() und was nicht?
verify() versucht, festzustellen, ob die Datei beschädigt ist, ohne jedoch die Bilddaten zu decodieren. Bei Problemen wird eine Ausnahme ausgelöst, und um das Bild weiter zu benutzen, muss es erneut geöffnet werden.
Aus Sicht der Sicherheit lassen sich zwei Punkte festhalten:
- Vorteil: Durch das Vermeiden der Decodierung (ein aufwändiger Prozess) lassen sich schnell „beschädigte“ Dateien aussortieren.
- Grenze: Ein erfolgreicher
verify()-Aufruf bedeutet nicht, dass die Datei völlig sicher ist – es zeigt lediglich, dass sie nicht sofort stark beschädigt erscheint. Probleme können erst beiload()sichtbar werden.
load() ist gefährlich, wenn es in der Validierung zu früh aufgerufen wird
load() führt die eigentliche Decodierung (inkl. Entpackung) durch und lädt die Pixel in den Speicher. Dieser Schritt ist sofort ein potenzieller DoS‑Angriffspunkt, weil die Datei zwar klein erscheinen kann, aber nach der Decodierung sehr groß wird.
Pillow warnt vor dem „Decompression-Bomb“-Risiko und hat Schutzmechanismen mit Standard-Schwellenwerten (z. B. etwa 128 Mpx). Django nutzt aus demselben Grund verify() statt load() in der Bild‑Upload‑Validierung. In der Quelle steht explizit: „load() lädt das gesamte Bild in den Speicher und ist ein DoS‑Vektor.“ – und danach wird Image.open() gefolgt von verify() aufgerufen.
Django/DRF: ImageField und das doppelte verify()
Django‑Formulare führen intern Image.open() + verify() aus. Auch serializers.ImageField von DRF delegiert die Validierung an Django.
Wenn Sie bereits serializers.ImageField nutzen, dann:
- Ein zusätzlicher Aufruf von
verify()invalidate()ist meist überflüssig. - Für strengere Geschäfts‑ oder Sicherheitsprüfungen kann es sauberer sein, stattdessen ein
FileFieldzu verwenden und die Validierung selbst zu gestalten.
Wie kann man die Sicherheit von hochgeladenen Dateien gewährleisten?

Die praktischste Lösung lautet:
open(): Leichte Infos (Format, Größe) auslesen und mit Richtlinien blockieren.verify(): Offensichtlich beschädigte Dateien entfernen.- Decodieren: In einer kontrollierten Umgebung (z. B. Worker/isolierter Prozess) decodieren und in ein Standard‑Pixelformat (RGB/RGBA) normalisieren.
- Neu‑Kodieren: Das Ergebnis in einem vom Server gewählten Format speichern.
- Nur die neu erzeugte Datei wird gespeichert und ausgeliefert.
Vorteil: Der Server behält die Kontrolle über das Endformat und kann unerwünschte Metadaten oder ungewöhnliche Strukturen entfernen.
Nachteile: Die Neu‑Kodierung beinhaltet immer noch einen load()‑ähnlichen Schritt. Daher sollten Pixel‑/Speicher‑Grenzen gesetzt und die Verarbeitung idealerweise in einem isolierten Prozess stattfinden.
Fazit
open()– Identifikation + leichte Infos (Pixel noch nicht geladen)verify()– Erster Filter für Beschädigungen (ohne Decodierung, für die Weiterverwendung erneut öffnen)load()– Beginn der Decodierung und Speicher‑Nutzung (in der Validierung zu vermeiden)- Sicherer Upload – Server‑seitiges Neu‑Kodieren (mit Grenzen/Isolation)
Weiterführende Artikel:
Es sind keine Kommentare vorhanden.