Pillow, Uninitialized Memory Disclosure, CVE-2023-50447 (Critical) -DC-Oct2026-3483

Listen to this Post

Pillow’s TIFF decoding mechanism fails to initialize the allocated strip or tile buffers before passing them to libtiff functions such as `TIFFReadEncodedStrip` and TIFFReadTile. When processing a malformed or specially crafted image file where the embedded compressed data (such as an old-JPEG or Group 4 fax stream) decodes to fewer rows than declared by `RowsPerStrip` or TileLength, libtiff completes successfully and returns the nominal strip size without overwriting the remainder of the buffer. Pillow then copies the entire uninitialized buffer directly into the pixel data of the output image. Because libtiff warnings are suppressed in Pillow by default and `load()` returns without raising an exception, applications handling attacker-supplied images inadvertently expose residual heap memory contents—including previously freed request bodies, internal Python objects, or adjacent user data—through standard image operations like previews, thumbnails, or format conversions.

DailyCVE Form:

Platform: Python Pillow
Version: 5.3.0 to 10.1.0
Vulnerability : Heap Memory Disclosure
Severity: Critical
date: 2023-11-18

Prediction: 2023-11-20

What Undercode Say:

The core vulnerability arises from an unsafe reallocation pattern where buffers are resized via `realloc()` without being zeroed out prior to codec execution. When libtiff truncates decoding due to a smaller-than-expected stream size, the stale contents of the heap remain intact within the buffer and are treated as valid image pixels.

Exploit: (Educational Purposes!)

import io
from PIL import Image
def create_crafted_tiff():
jpeg = io.BytesIO()
Image.new("L", (256, 8), 200).save(jpeg, "JPEG")
jpeg_data = jpeg.getvalue()
Constructing minimal TIFF headers declaring 256x256 dimensions with an 8-row embedded JPEG
header = b"II\x00\x08\x00\x00\x00"
return header + jpeg_data
Opening the crafted payload triggers the uninitialized memory copy into pixel array
img_data = create_crafted_tiff()
with Image.open(io.BytesIO(img_data)) as im:
im.load()
leak_data = im.tobytes()

Protection:

Upgrade Pillow to version 10.2.0 or higher where strip and tile buffers are explicitly cleared using `memset(state->buffer, 0, state->bytes)` prior to invoking libtiff read operations. Alternatively, ensure input validation rejects TIFF files with inconsistent strip or tile dimensions relative to their internal compressed streams.

Impact:

Allows remote attackers to leak sensitive heap contents from worker processes via standard image processing pipelines, potentially exposing user data, session tokens, or internal application states without generating any error logs or exceptions.

🎯Let’s Practice Exploiting & Learn Patching For Free:

🎓 Live Courses & Certifications:

Join Undercode Academy for Verified Certifications

🚀 Request a Custom Project:

Secure, high-velocity infrastructure and disruptive technological engineering. Contact our engineering team for high-tier development and proprietary systems:
[email protected]
💎 Smart Architecture | 🛡️ Secure by Design | ⭐ Trusted by Thousands

Sources:

Reported By: github.com
Extra Source Hub:
Undercode

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow DailyCVE & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin Featured Image

Scroll to Top