大模型网关工具 LiteLLM 10 月 21 日遭遇供应链投毒。云安全公司 Wiz 披露,被篡改的 LiteLLM 1.107.0 当天在 PyPI 上架,GHCR 和 Docker Hub 上打着 v1.107.0、latest、main-latest、main-stable 标签的镜像也被植入了同一套窃密程序。官方给出的最近一个安全版本是 v1.106.2。
LiteLLM 由 BerriAI 开发,常见用法是在企业内部架一层代理,用统一接口转发到 OpenAI、Anthropic、Bedrock 等上百个模型服务。代理背后存着各家厂商的 API 密钥,这次攻击瞄准的正是这一点。
装上就开始偷
恶意包会往 site-packages 根目录放三个文件:cook.pth、cook.py 和 sitecustomize.py。前两个借助 Python 的 .pth 机制,只要解释器启动就会执行,并不需要业务代码 import LiteLLM。
窃密程序内部叫 privcollect,共 16 个模块,覆盖的目标包括:
- Chrome、Firefox、Edge、Safari 的浏览器凭据和 Cookie
- AWS、GCP、Azure 的云凭据
- OpenAI、Anthropic、Cohere 等 AI 厂商的 API 密钥
- SSH、GPG 私钥和 shell 历史
- 从 LiteLLM Proxy 的 PostgreSQL 数据库里直接查出的上游厂商凭据
数据先用 AES-256-CBC 加密,密钥再用 RSA-4096 包一层,通过 HTTP POST 发到攻击者注册的仿冒域名 www.litellm[.]dev。sitecustomize.py 只在 Linux 和 macOS 上运行,会去 GitHub 上一个”死信箱”仓库取第二阶段地址;Wiz 称这个文件除了测试值之外一直没填内容,GitHub 已删库。
把时间线摊开
按 Wiz 公布的 UTC 时间粗算一下各个窗口:
| 环节 | 时间(UTC) | 持续 |
|---|---|---|
| 仿冒仓库推送 10 次提交 | 08:56–10:46 | 约 1 小时 50 分 |
| PyPI 恶意版本在线 | 11:39–13:20 | 约 1 小时 41 分 |
| Docker 被篡改标签在线 | 至 13:53 前后下架 | PyPI 上架起算约 2 小时 14 分 |
| 攻击者验证 AWS 凭据 | 16:20–17:01 | 距外传约 4.5 小时 |
PyPI 那一个多小时看上去不长,但 latest 这类标签会被大量 CI 流水线和 Kubernetes 部署自动拉取,暴露面主要取决于这段时间里有多少环境重建过镜像。Wiz 没有给出下载量,受影响的组织数量目前也无法核实。
攻击者拿到凭据后,用被入侵 CI runner 和 Kubernetes 节点上的 AWS 实例角色调用了 sts:GetCallerIdentity、bedrock:ListFoundationModels 等接口。Wiz 认为这与 LLMjacking 的手法一致,也就是盗用别人的云账号白嫖大模型调用;在部分环境里,攻击者还枚举了 IAM 做常规侦察。
入口怀疑是 GitHub 令牌
攻击者推送的那 10 次提交落在仿冒仓库 Berri-AI/litellm,前 9 次带 GitHub 签名,最后一次没签名、邮箱也换了。BerriAI 方面的说法是:
“malicious actions were taken through three engineers’ GitHub accounts” (恶意操作是通过三名工程师的 GitHub 账号完成的。)
LiteLLM 怀疑这几枚 GitHub CLI OAuth 令牌是从一个暴露在公网的内部部署里泄露的,可能和一个刚修补的漏洞有关,这一点 Wiz 明确写了尚未证实。BerriAI 称涉事令牌已全部吊销。用过 1.107.0 或在那段时间拉过上述镜像的团队,需要把机器上能读到的云凭据、模型密钥和 SSH 私钥全部轮换一遍。
参考来源:CocoLoop、Wiz 研究博客、Wiz 威胁情报中心通告、BerriAI 公开声明;核验受影响版本与镜像标签、恶意文件名及各环节 UTC 时间。