Pillow: Heap buffer overflow in ImagingJpegDecode
A heap-based buffer overflow in Pillow’s ImagingJpegDecode function occurs when processing lossless (SOF3) JPEG files, leading to out-of-bounds memory writes during scanline decompression.
Triage facts
Revision 1- Applicability
- Pillow
- Evidence
- Unknown
- Severity
- High
- Action
- Elevated
- Sources
- 1 public source
- Freshness
- Revision 1Oct 20, 23:53 UTC
- Source quality
- A1Likely
Pillow contains a heap-based buffer overflow vulnerability within the ImagingJpegDecode function. The issue arises when the library processes lossless (SOF3) JPEG images while performing downscaling, such as when calling Image.thumbnail() or JpegImageFile.draft(). When these methods request a scaled output, Pillow shrinks the internal decode buffer to match the expected scaled dimensions. However, the underlying libjpeg-turbo implementation ignores the scaling request for lossless (SOF3) streams and writes full-width scanlines into the undersized buffer.
An attacker can exploit this by providing a maliciously crafted, standards-compliant 8-bit grayscale lossless JPEG. The buffer overflow occurs because there is no geometry validation comparing the libjpeg output dimensions against the allocated state->buffer. Depending on the image dimensions and requested scaling factors, this can result in writing attacker-controlled pixel data past the end of the heap-allocated buffer. While the library ultimately throws an OSError due to geometry mismatches, the memory corruption occurs during the decompression process.
Attack Chain
- Attacker crafts a standards-compliant 8-bit grayscale lossless (SOF3) JPEG image file.
- Attacker hosts or delivers the file to a target system utilizing a vulnerable version of Pillow.
- The victim application calls
Image.open()on the malicious file, which is parsed successfully by Pillow's SOF parser. - The application calls
Image.thumbnail()orJpegImageFile.draft()on the image object, triggering a scaling request (e.g., scale factor s >= 2). - Pillow computes expected scaled dimensions and allocates a
state->bufferusingcallocbased on the reduced size. - The
ImagingJpegDecodefunction callsjpeg_start_decompressand proceeds tojpeg_read_scanlineswithout validating the actual JPEG output dimensions. - libjpeg-turbo writes the full-width pixel scanlines into the undersized buffer, causing an out-of-bounds heap write of
(W - ceil(W/s)) x componentsbytes. - The overflow corrupts heap memory with attacker-controlled pixel values.
Impact
Successful exploitation allows for memory corruption on systems using Pillow to process user-supplied images. This can lead to application crashes or potentially arbitrary code execution depending on the heap layout and the ability to influence memory state through crafted pixel data. This vulnerability affects any system or service that automatically generates thumbnails or processes image uploads using Pillow with standard library defaults.
Recommendation
- Identify and inventory all applications within the environment that utilize the Pillow library for image processing.
- Implement strict input validation or sanitization for JPEG files to detect or reject lossless (SOF3) images if the functionality is not explicitly required.
- Monitor internal application logs for
OSErrorexceptions originating fromPIL.JpegImagePluginorlibImagingduring image processing, as these may indicate attempted exploitation. - Apply patches provided by the Pillow project as soon as they become available for the affected versions.
Immediate actions
Inventory applications using Pillow and prepare for deployment of patched versions.
Threat Hunt
Monitor application logs for frequent OSErrors in Pillow image processing pipelines.
Data: Application exception logs
Mitigations
Upgrade Pillow to the latest version once the fix is released.
Pillow