Średnia

Dekoder kafelkowanych obrazów TIFF w Pillow odczytuje dane poza buforem kafelka w copy4 (Unpack.c:1290)

  • Ujawniono: 20.10.2026
  • Aktualizacja: 20.10.2026 23:28

Podsumowanie

Dekoder _decodeTile w libImaging biblioteki Pillow, służący do dekodowania kafelkowanych obrazów TIFF, alokuje bufor dla każdego kafelka za pomocą realloc(state->buffer, TIFFTileSize(tiff)). Po każdym wywołaniu TIFFReadTile wykonuje iterację zmiennej tile_y od 0 do current_tile_length i wywołuje skonfigurowany mechanizm rozpakowywania wierszy (tutaj copy4) ze wskaźnikiem źródłowym state->buffer + tile_y * row_byte_size. Kiedy libtiff zwraca wartość tile_bytes_size mniejszą niż pesymistyczny przypadek row_byte_size * tile_length, wewnętrzna pętla kroku i kopiowania wykracza poza realokowany obszar, a funkcja copy4 wykonuje operację memcpy o wielkości 1024 bajtów, która odczytuje do (tile_length-1) * row_byte_size + row_byte_size bajtów z bufora o rozmiarze zaledwie tile_bytes_size. Dostarczony plik PoC TIFF wywołuje odczyt poza zakresem o wielkości 1024 bajtów dokładnie 0 bajtów za alokacją wynoszącą 196608 bajtów. Osoba atakująca, która nakłoni aplikację korzystającą z Pillow do zdekodowania spreparowanego pliku TIFF, może spowodować awarię procesu (DoS) oraz doprowadzić do skopiowania sąsiadującej pamięci sterty do zdekodowanego bufora pikseli.

Szczegóły

Gdy libtiff zgłasza, że plik jest kafelkowany, dekoder TIFF w Pillow wybiera ścieżkę _decodeTile. Funkcja ta:

  1. Odpytuje libtiff o TIFFTileSize(tiff) (liczbę bajtów na kafelek) oraz TIFFTileRowSize(tiff) (liczbę bajtów na wiersz w postaci zapisanej przez libtiff).
  2. Realokuje state->buffer do dokładnie tile_bytes_size.
  3. Dla każdego punktu początkowego kafelka (x, y) i każdej płaszczyzny wywołuje TIFFReadTile do state->buffer, a następnie przetwarza kafelek wiersz po wierszu, wywołując skonfigurowany ImagingShuffler (tutaj copy4) dla porcji bajtów źródłowych każdego wiersza.

Weryfikacja przeprowadzana przed pętlą ma postać:

c
if (tile_bytes_size > ((tile_length * state->bits / planes + 7) / 8) * tile_width) {
    state->errcode = IMAGING_CODEC_BROKEN;
    return -1;
}

Odrzuca ona zbyt duże kafelki libtiff, jednak nie odrzuca kafelków zbyt małych — tj. sytuacji, gdy libtiff zwraca wartość tile_bytes_size ściśle mniejszą niż row_byte_size * tile_length. Ciało pętli indeksuje bufor przy założeniu, że ma on co najmniej row_byte_size * tile_length bajtów długości.

Podatny kod

c
// 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
                );
            }
        }
    }
}
c
// 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
}

Metadane kafelka w PoC dają tile_width = tile_length = 256, row_byte_size = 1024 (4 bajtów/piksel × 256 pikseli) oraz tile_bytes_size = 196608 (co daje 256·256·3 = trzykanałowy magazyn bajtów). Realokowany bufor ma rozmiar 196608 bajtów. Mechanizm rozpakowywania iteruje tile_y od 0 do 255, a dla najwyższych wierszy wskaźnik źródłowy state->buffer + tile_y * 1024 znajduje się już na poziomie przesunięcia 196608 lub poza nim — wywołanie memcpy(in=buffer+255·1024, 1024) dla ostatniego wiersza odczytuje 1024 bajtów, zaczynając 260096 - 196608 = 63488 bajtów za alokacją; ASAN zgłasza już pierwszy bajt poza obszarem sterty (READ of size 1024 at … 0 bytes after 196608-byte region).

Niezgodność jest faktyczna: funkcja TIFFTileSize w libtiff zwraca spakowany rozmiar kafelka (który zależy od układu fotometrycznego/separacji w pliku — może być zgodnie ze standardem mniejszy niż row_byte_size × tile_length), podczas gdy pętla wewnętrzna przesuwa się tak, jakby bufor zawsze był równy row_byte_size × tile_length.

Źródło

Problem ten został znaleziony przez firmę Anthropic przy użyciu modelu Claude do badania bezpieczeństwa projektów open source, a ja reprezentuję Ada Logics, pomagając w weryfikacji znalezionych problemów i zgłaszaniu ich twórcom oprogramowania. Dane zawarte w tym raporcie zostały sprawdzone ręcznie.

Co trzeba zrobić

Zaktualizuj bibliotekę Pillow do wersji 13.0.0 lub nowszej.

Czego dotyczy

Kliknij technologię, aby zobaczyć wszystkie dotyczące jej podatności.

PlatformaPaczkaPodatne wersjePoprawka w wersji
Python (PyPI) pillow >= 8.2.0, < 13.0.0 13.0.0

Odnośniki

Ocena CVSS 6.5/10
Wektor CVSS
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:L
Słabość (CWE)
CWE-122
Platforma
Python (PyPI)
Paczka
pillow
Ujawniono
20.10.2026
Aktualizacja
20.10.2026 23:28

Źródła i licencje · Redakcja lub tłumaczenie: DockRay. Zachowano prawa źródeł i obowiązujące licencje.

OSV / GitHub Advisory Database - GHSA-462x-pgg6-55fp - CC BY 4.0

Historia podatności: pillow

Wszystkie opisane podatności tej paczki (Python (PyPI)), od najnowszej. Widać, czy to jednorazowa wpadka, czy paczka, której trzeba pilnować.

Wszystkie (81) w archiwum
Wszystkich wpisów
81
Pierwsza → ostatnia
04.2014 10.2026
Bez poprawki
0
Wykorzystywana w atakach
1

Rozkład istotności

  • Krytyczna 10
  • Wysoka 53
  • Średnia 16
  • Niska 1
  • Nieoceniona 1

Ujawnienia w latach

  1. 2017: 1
  2. 2018: 0
  3. 2019: 1
  4. 2020: 10
  5. 2021: 20
  6. 2022: 8
  7. 2023: 3
  8. 2024: 2
  9. 2025: 1
  10. 2026: 23

wcześniej: 12

Istotność:
  1. Dekoder kafelkowanych obrazów TIFF w Pillow odczytuje dane poza buforem kafelka w copy4 (Unpack.c:1290) ten wpis
    Średnia · 6.5 CVE-2026-112395 >= 8.2.0, < 13.0.0 13.0.0
  2. Wysoka · 7.5 CVE-2026-59200 >= 5.1.0, < 12.3.0 12.3.0
  3. Wysoka CVE-2026-42311 >= 10.3.0, < 12.2.0 12.2.0
  4. Wysoka · 7.5 CVE-2026-40192 >= 10.3.0, < 12.2.0 12.2.0
  5. Wysoka CVE-2026-25990 >= 10.3.0, < 12.1.1 12.1.1
  6. Wysoka · 7.1 CVE-2025-48379 >= 11.2.0, < 11.3.0 11.3.0
  7. Wysoka · 6.7 CVE-2024-28219 < 10.3.0 10.3.0
  8. Krytyczna · 8.1 CVE-2023-50447 < 10.2.0 10.2.0
Pokaż więcej (20) Widać 20 z 64

Dowiedz się, które podatności dotyczą Twojej aplikacji

Po podłączeniu integracji DockRay i włączeniu raportowania oprogramowania DockRay porównuje zgłoszone wersje komponentów ze znanymi podatnościami i powiadamia o potwierdzonych dopasowaniach. Zakres zależy od obsługiwanej technologii i dostępnych biuletynów.

Podłącz swoją aplikację
Newsletter DockRay

Bezpieczeństwo aplikacji w Twojej skrzynce

Najważniejsze podatności, konkretne zalecenia i praktyczne wskazówki dla Twoich aplikacji. Wybierz technologie i śledź to, co ma znaczenie dla Twojego projektu.

  • Codzienne zestawienie nowych podatności, także krytycznych.
  • Powiadomienia o ważnych aktualizacjach.
  • Praktyczne porady o bezpieczeństwie i monitoringu aplikacji.

Pozostaw puste, aby otrzymywać informacje o wszystkich technologiach.

Zapis jest bezpłatny. Wypiszesz się jednym kliknięciem w wiadomości.