The SonicWall Capture Labs threat research team became aware of the threat CVE-2023-6018, assessed its impact and developed mitigation measures for this vulnerability.
CVE-2023-6018 is a critical flaw in MLflow (from LF Projects) that allows unauthenticated attackers to overwrite arbitrary files on the server hosting the application. With a CVSS score of 9.8 (according to NIST), it stems from improper neutralization of special elements used in OS commands (CWE-78). An attacker can exploit this flaw to achieve remote code execution or otherwise compromise the server’s integrity and availability. The Exploit Prediction Scoring System (EPSS) currently assigns a 93.02% probability of exploitation within 30 days, placing this threat in the 99th percentile of vulnerabilities most likely to be exploited. For further details, consult the advisories on huntr.dev and the National Vulnerability Database. To mitigate exposure, organizations should promptly apply security patches, restrict network access to MLflow servers and follow vendor-provided remediation steps.
A newly discovered vulnerability under CVE-2023-6018 affects MLflow by allowing an attacker to overwrite any file on the hosting server without authentication. This is especially dangerous given MLflow’s role in managing machine learning workflows and storing sensitive data. By sending malicious parameters to the model version endpoints, an attacker can craft requests that exploit file-handling logic, leading to remote code execution and significant data compromise.
The issue resides in MLflow’s artifact-handling code (mlflow/mlflow/store/artifact/artifact_repo.py on GitHub). The system fails to sanitize file paths returned by remote artifact URLs, enabling arbitrary file writes on the victim machine. When MLflow receives artifact listings containing file paths such as "/etc/passwd" or "/usr/local/lib/python3.10/dist-packages/malicious.pth", it overwrites critical system files. Below is a snippet showing the vulnerable download logic:
Lines 2–8 iterate over artifact entries and call _download_file (line 7) for each file. Notably, file_info.path is passed in verbatim, meaning MLflow accepts the path from the attacker’s JSON without validating it. Then, at lines 12–14, _download_file invokes _create_download_destination(), which appends file_info.path directly to the local destination, allowing absolute or traversal paths (e.g., /etc/passwd, ../../secret). Consequently, malicious inputs can overwrite arbitrary files on the server, resulting in a critical file‐write vulnerability.
An attacker can escalate privileges by targeting .pth files or other system-sensitive paths, enabling remote code execution when Python next launches. Below is an example screenshot showing how a rogue server response can force MLflow to write arbitrary files on the victim’s file system:
In broad terms, an attacker needs only network access to the MLflow instance. They register or reference a malicious model source that points to a rogue server, which returns a specially crafted JSON file listing paths such as /etc/passwd or .pth files. MLflow then writes those files locally when the attacker calls the “get-artifact” endpoint. Details of these steps appear in the “Exploitation” section below.
This section demonstrates how an attacker—who merely needs network access to a publicly reachable MLflow instance—can exploit its arbitrary file write vulnerability by creating multiple model versions that “chain” together. In default installations, MLflow often requires no authentication, letting an attacker register a model and point its artifact location to a rogue server. By referencing one model version from another and ultimately sending a single “get-artifact” request, the attacker forces MLflow to trust a malicious JSON response, blindly write files specified by the attacker onto the victim’s file system, and thus gain remote code execution or system compromise. The images below illustrate each of the four steps in this chain-based exploitation process.
The attacker begins by sending a POST request to create a new registered model on the victim’s MLflow instance. This step establishes a named model (“poc”) in the MLflow registry:
In this request, the attacker provides a name field with the value “poc.” Under normal circumstances, this defines a placeholder model in the registry. However, because MLflow does not require authentication by default, the attacker can do this without any prior permission.
Next, the attacker creates the first model version. This is where the malicious source URI pointing to the rogue server (192.168.2.145:4444) is introduced:
The source parameter is crucial. MLflow will eventually attempt to fetch artifacts from the specified endpoint. By specifying the rogue server’s HTTP URI (http://192.168.2.145:4444/api/2.0/mlflow-artifacts/artifacts/), the attacker effectively instructs MLflow to trust and download artifact listings from an untrusted source.
The attacker then creates a second model version that references the first via models:/poc/1:
By chaining model version 2 to “models:/poc/1,” MLflow’s artifact logic is forced to consult version 1’s location if version 2’s artifacts are requested. Since version 1 points to the malicious HTTP endpoint, MLflow will end up querying the attacker’s server to download the associated files.
Finally, the attacker makes a GET request to retrieve an artifact named “random” from version 2:
This prompts MLflow to walk through the chain:
The video in Figure 7 demonstrates triggering the artifact being downloaded.
Figure 7: Trigger Responses
To ensure SonicWall customers are prepared for any exploitation that may occur due to this vulnerability, the following signatures have been released:
The risks posed by this vulnerability can be mitigated or eliminated by:
Share This Article
An Article By
An Article By
Security News
Security News