Pillow-Decoder für gekachelte TIFFs liest über Kachelpuffer hinaus in copy4 (Unpack.c:1290)
Zusammenfassung
Der Decoder _decodeTile in Pillows libImaging, der zum Dekodieren von gekachelten TIFF-Bildern verwendet wird, alloziiert über realloc(state->buffer, TIFFTileSize(tiff)) einen Puffer pro Kachel. Nach jedem TIFFReadTile iteriert er tile_y von 0 bis current_tile_length und ruft den konfigurierten Zeilen-Unpacker (hier copy4) mit dem Quellzeiger state->buffer + tile_y * row_byte_size auf. Wenn libtiff einen Wert für tile_bytes_size zurückgibt, der kleiner als der Worst-Case row_byte_size * tile_length ist, läuft die innere Stride-and-Copy-Schleife über den reallokierten Bereich hinaus, und copy4 führt eine 1024-Byte-Operation memcpy aus, die bis zu (tile_length-1) * row_byte_size + row_byte_size Bytes aus einem Puffer liest, der nur für tile_bytes_size dimensioniert ist. Das bereitgestellte PoC-TIFF löst einen Überlesevorgang von 1024 Bytes genau 0 Bytes hinter einer Allokation von 196608 Bytes aus. Ein Angreifer, der eine Pillow nutzende Anwendung dazu bringen kann, ein manipuliertes TIFF zu dekodieren, kann einen Prozessabsturz (Denial of Service) herbeiführen und möglicherweise veranlassen, dass benachbarter Heap-Speicher in den dekodierten Pixelpuffer kopiert wird.
Details
Wenn libtiff meldet, dass die Datei gekachelt ist, nimmt der TIFF-Decoder von Pillow den Pfad _decodeTile. Die Funktion:
- Fragt libtiff nach
TIFFTileSize(tiff)(den Bytes pro Kachel) undTIFFTileRowSize(tiff)(den Bytes pro Zeile wie von libtiff gespeichert). - Reallokiert
state->bufferauf genautile_bytes_size. - Ruft für jeden Kachelursprung
(x, y)und jede EbeneTIFFReadTilenachstate->bufferauf und durchläuft die Kachel dann Zeile für Zeile, wobei der konfigurierteImagingShuffler(hiercopy4) auf den Quelldaten jeder Zeile aufgerufen wird.
Die vor der Schleife durchgeführte Validierung lautet:
if (tile_bytes_size > ((tile_length * state->bits / planes + 7) / 8) * tile_width) {
state->errcode = IMAGING_CODEC_BROKEN;
return -1;
}
Dies weist überdimensionierte Kacheln von libtiff ab, verwirft jedoch keine unterdimensionierten Kacheln – also den Fall, in dem libtiff ein tile_bytes_size zurückgibt, das strikt kleiner als row_byte_size * tile_length ist. Der Schleifenkörper greift jedoch auf den Puffer unter der Annahme zu, dass dieser mindestens row_byte_size * tile_length Bytes lang ist.
Anfälliger Code
// src/libImaging/TiffDecode.c:446-490 — _decodeTile
new_data = realloc(state->buffer, state->bytes); // bytes = tile_bytes_size
if (!new_data) { ... }
state->buffer = new_data;
for (y = state->yoff; y < state->ysize; y += tile_length) {
for (plane = 0; plane < planes; plane++) {
ImagingShuffler shuffler = unpackers[plane];
for (x = state->xoff; x < state->xsize; x += tile_width) {
if (TIFFReadTile(tiff, (tdata_t)state->buffer, x, y, 0, plane) == -1) { ... }
current_tile_width = min((INT32)tile_width, state->xsize - x);
current_tile_length = min((INT32)tile_length, state->ysize - y);
for (tile_y = 0; tile_y < current_tile_length; tile_y++) {
shuffler(
(UINT8 *)im->image[tile_y + y] + x * im->pixelsize,
state->buffer + tile_y * row_byte_size, // <-- OOB stride
current_tile_width
);
}
}
}
}
// src/libImaging/Unpack.c:1288-1291 — copy4 (the crash site)
static void
copy4(UINT8 *out, const UINT8 *in, int pixels) {
/* RGBA, CMYK quadruples */
memcpy(out, in, 4 * pixels); // <-- ASAN-detected READ here
}
Die Kachel-Metadaten des PoC ergeben tile_width = tile_length = 256, row_byte_size = 1024 (4 Bytes/Pixel × 256 Pixel) und tile_bytes_size = 196608 (was 256·256·3 = Dreikanal-Byte-Speicher entspricht). Der reallokierte Puffer ist 196608 Bytes groß. Der Unpacker iteriert tile_y von 0 bis 255, und bei den obersten Zeilen liegt der Quellzeiger state->buffer + tile_y * 1024 bereits an oder hinter Offset 196608 – das memcpy(in=buffer+255·1024, 1024) der allerletzten Zeile liest 1024 Bytes beginnend 260096 - 196608 = 63488 Bytes hinter der Allokation; ASAN markiert bereits das allererste Byte hinter dem Heap-Bereich (READ of size 1024 at … 0 bytes after 196608-byte region).
Die Diskrepanz ist real: TIFFTileSize von libtiff gibt den gepackten Kachelspeicherplatz zurück (der vom photometrischen/Separations-Layout der Datei abhängt – er kann legitim kleiner sein als row_byte_size × tile_length), während die innere Schleife so voranschreitet, als ob der Puffer immer gleich row_byte_size × tile_length wäre.
Danksagung
Dieses Problem wurde von Anthropic bei der Untersuchung der Sicherheit von Open-Source-Projekten mithilfe von Claude entdeckt, und ich von Ada Logics helfe bei der Validierung der gefundenen Probleme und der Meldung an die Maintainer. Die Daten in diesem Bericht wurden manuell überprüft.
Was zu tun ist
Aktualisieren Sie Pillow auf Version 13.0.0 oder neuer.
Betroffene Software
Klicken Sie auf eine Technologie, um alle zugehörigen Schwachstellen anzuzeigen.
| Plattform | Paket | Anfällige Versionen | Behoben in |
|---|---|---|---|
| Python (PyPI) | pillow | >= 8.2.0, < 13.0.0 | 13.0.0 |
Verweise
- https://github.com/python-pillow/Pillow/security/advisories/GHSA-462x-pgg6-55fp
- https://nvd.nist.gov/vuln/detail/CVE-2026-112395
- https://github.com/python-pillow/Pillow/commit/76869efdbbf2ad7dccd7536520fb61b7a00ab61e
- https://github.com/python-pillow/Pillow
- https://github.com/python-pillow/Pillow/releases/tag/13.0.0
- CVSS-Vektor
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L- Schwäche (CWE)
CWE-122- Plattform
- Python (PyPI)
- Paket
pillow- Veröffentlicht
- 20.10.2026
- Aktualisiert
- 20.10.2026 23:28
Quellen und Lizenzen · Von DockRay bearbeitet oder übersetzt; Rechte und Lizenzen der Quellen bleiben erhalten.
OSV / GitHub Advisory Database - GHSA-462x-pgg6-55fp - CC BY 4.0
Schwachstellenhistorie: pillow
Alle veröffentlichten Schwachstellen dieses Pakets (Python (PyPI)), neueste zuerst. Zeigt, ob es ein einmaliger Ausrutscher ist oder ein Paket, das man im Auge behalten muss.
- Einträge insgesamt
- 81
- Erste → letzte
- 04.2014 10.2026
- Ohne Fix
- 0
- In Angriffen ausgenutzt
- 1
Verteilung nach Schweregrad
- Kritisch 10
- Hoch 53
- Mittel 16
- Niedrig 1
- Nicht bewertet 1
Veröffentlichungen pro Jahr
- 2017: 1
- 2018: 0
- 2019: 1
- 2020: 10
- 2021: 20
- 2022: 8
- 2023: 3
- 2024: 2
- 2025: 1
- 2026: 23
früher: 12
-
Pillow-Decoder für gekachelte TIFFs liest über Kachelpuffer hinaus in copy4 (Unpack.c:1290) dieser Eintrag
Erkennen Sie Schwachstellen in Ihrer Anwendung
Mit der DockRay-Integration und aktivierter Softwareinventarisierung prüft DockRay gemeldete Komponentenversionen auf bekannte Schwachstellen und benachrichtigt Sie über bestätigte Treffer. Die Abdeckung hängt von der unterstützten Technologie und den verfügbaren Meldungen ab.