系统:运行中
← 返回所有攻击
SUPPLY CHAIN CRITICAL NEW

Vertex AI 中的存储桶抢注:跨租户 RCE「Pickle in the Middle」

Unit 42 于 2026 年 6 月 16 日披露了 Vertex AI Python SDK 的一个缺陷:可预测的暂存存储桶名称加上缺失的所有权校验,使攻击者得以劫持受害者的模型上传并实现跨租户代码执行。已在 v1.148.0 修复。

2026-06-22 // 5 min affects: google-vertex-ai, google-cloud-aiplatform <1.144.0

这是什么?

2026 年 6 月 16 日,Palo Alto Networks 旗下 Unit 42(研究员 Ori Hadad)发布了 Pickle in the Middle,披露了 Google Cloud Vertex AI Python SDKgoogle-cloud-aiplatform)中的一个漏洞。在 Google 修复之前,该缺陷允许攻击者完全从自己的 Google Cloud 项目出发——无需对受害者项目的任何访问权限——劫持受害者的机器学习模型上传、将其投毒,并在 Vertex AI 的服务基础设施内实现远程代码执行(RCE)

该漏洞于 2026 年 3 月 5 日通过 Google 漏洞奖励计划上报,并在公开披露前已完全修复:第一个补丁为 v1.144.0(2026 年 3 月 31 日),第二个为 v1.148.0(2026 年 4 月 15 日)。受影响版本为 1.139.0 和 1.140.0。这是一个已完整披露并修复的问题——我们讲解的是机理与教训,而非可直接利用的攻击。

工作原理

该攻击串联了两个看似平平无奇的弱点。

首先是可预测的默认存储桶名称。当开发者上传模型而未指定 staging_bucket 时,SDK 会基于项目 ID 与区域按确定性模式构造一个 Cloud Storage 存储桶名称。由于 GCS 存储桶名称在整个 Google Cloud 内全局唯一,任何能猜到该名称的人都可以在自己的项目中抢先创建它——这类攻击称为存储桶抢注(bucket squatting)(与 slopsquatting 和依赖混淆采用相同的命名冲突逻辑)。

其次是缺失的所有权校验。SDK 仅调用 bucket.exists(),发现(归攻击者所有的)存储桶已存在,便悄无声息地把受害者的工件暂存到那里。攻击者授予恰当的 IAM 角色,使受害者的上传和 Vertex AI 服务代理都能成功——一切看起来都没出问题。

接下来便是一场赛跑。攻击者在 google.storage.object.finalize 事件上预设一个 Cloud Function:受害者的 model.joblib 一落地,就被替换为恶意工件。据 Unit 42 的概念验证,从受害者上传到 **Per-Product, Per-Project 服务账户(P4SA)**读取文件之间的窗口约为 2.5 秒,而事件触发的函数约 800 毫秒即可响应——足以每次都赢得这场赛跑。

载荷本身利用了 Python 序列化的一个众所周知的特性:ML 模型通常以 pickle(或其 Joblib 封装)存储,而 pickle.load() / joblib.load() 会在任何校验之前执行 __reduce__ 方法。当 Vertex AI 的服务代理反序列化被替换的模型时,攻击者代码便在 Google 托管的租户项目内运行。在 Unit 42 的测试中,该代码从 GCE 元数据服务器取走了服务容器的 OAuth 令牌——该令牌可触及同一托管租户内的其他工件、BigQuery 元数据、租户日志与 GKE 集群名称。这正是整个 ML 技术栈中反复出现的不安全反序列化汇聚点,从 Transformers 配置注入GGUF 解析器 RCE 以及 vLLM 的 trust-remote-code 绕过

为何重要

受害者没有任何过错。复现使用的是标准 SDK 调用、无任何异常配置——Model.upload() 后接 deploy()。漏洞完全位于平台工具链之中,然而影响半径却是跨租户代码执行与凭据窃取,无需任何立足点,只需知道一个项目 ID 与区域(这些远非机密)。

它也重新定位了威胁。LLM 安全的关注大多集中在提示词与智能体上;此案提醒我们,模型供应链与开发者的云工具链才是头等攻击面。一个命名约定加上一处被省略的所有权校验,就足以把一次普通的 model.upload() 变成在提供商自身基础设施内的 RCE——与此前记录的 Vertex AI 服务代理权限问题 一脉相承。

防御

  • 升级 SDK。google-cloud-aiplatform 升级到 v1.148.0 或更高版本。补丁在暂存存储桶名称末尾追加随机 uuid4(终结可预测性),并在使用前增加存储桶所有权校验
  • 固定一个显式且归自己所有的暂存存储桶。 始终将 staging_bucket 设为你项目拥有的 Cloud Storage 位置,而非依赖确定性默认值。即便在已修复的 SDK 上,Unit 42 也将此列为长期最佳实践。
  • 将模型工件视为不可信代码。 经 pickle/Joblib 反序列化的一切都可能在加载时执行。尽量优先使用安全格式(如 safetensors),在部署前校验工件完整性(哈希/签名),并仅在沙箱化的最小权限环境中加载不可信模型。
  • 收紧服务代理与元数据的可达范围。 限制服务容器身份可访问的内容;约束元数据服务器暴露与出站流量(egress),使反序列化立足点无法向令牌与跨租户资源横移。
  • 总体上警惕命名冲突这一类问题。 存储桶/软件包/命名空间抢注都在利用全局唯一性的假设。审计任何从可猜测输入派生全局唯一资源名称、却不校验所有权的工具。

状态

项目详情
披露2026 年 3 月 5 日(Google VRP);2026 年 6 月 16 日公开
受影响google-cloud-aiplatform 1.139.0、1.140.0
首个补丁v1.144.0(存储桶名称加入随机 uuid4)—— 2026 年 3 月 31 日
完整修复v1.148.0(存储桶所有权校验)—— 2026 年 4 月 15 日
影响跨租户 RCE、模型投毒、凭据窃取——无需受害者项目访问权限
在野利用未见报告

结论并非「修好 Vertex AI 就万事大吉」。而是 AI 平台会继承云的一切经典弱点——可预测的资源名称、缺失的所有权校验、不安全的反序列化——并且模型上传路径如今已是你攻击面的一部分。那些早已固定自有存储桶、校验工件、并把序列化模型当作可执行代码对待的防御者,从一开始就未曾暴露。

Sources