LiteLLM 作为一款统一调用各类大模型 API 的 Python 库,它在 GitHub 上拥有超过 4 万颗星,月下载量高达 9500 万次。然而,近期发生的一起针对该库的供应链投毒攻击,不仅让全球开发者感到背脊发凉,更揭示了 Python 生态系统中潜藏的深层次安全漏洞。
攻击概述
本次攻击的核心在于,攻击者成功通过被盗的合法 PyPI 令牌(Token),向官方仓库推送了带有恶意代码的 LiteLLM 版本(1.82.7 和 1.82.8)。由于攻击者使用了合法凭证,即便开发者启用了 pip install --require-hashes 这种哈希校验机制,也无法拦截恶意版本,因为恶意文件的哈希值与 wheel 包的记录完全匹配。
一旦开发者在本地环境或服务器上运行 pip install 及其后续操作,一场波及整个开发栈的灾难便随之而来。
技术机理:利用 Python 解释器的“后门”
本次攻击最令人感到恐怖的特征在于其触发方式的隐蔽性。攻击者并未修改现有的函数逻辑,而是在安装包中注入了一个名为 litellm_init.pth 的文件,大小仅为 34KB。
在 Python 的加载机制中,.pth 文件原本用于配置路径。当 Python 解释器启动时,site 模块会自动处理这些文件。如果文件中的某一行以 import 开头,解释器将直接执行该行代码。攻击者正是利用这一特性,写入了如下恶意指令:
import os, subprocess, sys; subprocess.Popen([sys.executable, "-c", "import base64; exec(base64.b64decode('...'))"], ...)
这意味着:
- 1. 无需显式调用:开发者不需要在代码中
import litellm,甚至不需要调用任何相关函数。 - 2. 全场景触发:只要启动 Python 解释器(例如运行
pip、执行 python -c、IDE 启动语言服务器、或者使用 pytest 进行测试),恶意代码就会立刻静默执行。
恶意载荷:多层嵌套与全方位收割
攻击载荷采用了三层 Base64 嵌套结构,展现了极高的专业性与针对性:
- • 第二层:作为任务编排器,其中内嵌了攻击者的 4096 位 RSA 公钥,确保回传数据的安全性。
- • 第三层:这是一个极其贪婪的凭证收割器。它系统性地扫描系统关键目录(如
/home、/opt、/srv、/var/www、/app 等),目标涵盖了 SSH 密钥、AWS/GCP/Azure 云凭证、Kubernetes (K8s) Secrets、数据库密码、加密货币钱包以及 .env 文件中的各类 API Key。
获取数据后,收割器使用随机生成的 32 字节 AES 会话密钥加密数据,再利用 RSA-OAEP 加密该密钥,最后打包为 tpcp.tar.gz 异步发送至攻击者的仿冒域名 http://models.litellm.cloud。如果检测到 K8s 环境,攻击程序甚至会尝试部署特权 Pod 以实现集群内的横向扩散。
更棘手的是,攻击者还建立了持久化后门。恶意程序会在 ~/.config/sysmon/sysmon.py 注册一个 systemd 用户服务。该服务每 50 分钟向远程服务器获取新指令,并为了躲避沙箱分析特意设置了 5 分钟的启动延迟。这意味着即便用户卸载了 LiteLLM,后门依然会在系统中长期潜伏。
攻击链的讽刺:从安全工具开始
这场危机最荒谬的转折点在于攻击的起点:安全扫描工具 Trivy 率先被攻陷。
3 月 19 日,名为 TeamPCP 的攻击组织通过 Trivy 窃取了 LiteLLM 的 PyPI 发布令牌。3 月 24 日,他们直接向 PyPI 推送了投毒版本。原本用于保护开发者安全的工具,竟然成为了攻击者的跳板。
当社区在 GitHub 上提交 Issue 报告异常时,攻击者反应极快。在短短 102 秒内,他们动用了 73 个被盗账号发布了 88 条垃圾评论以淹没讨论,并使用被盗的维护者账号强行关闭了 Issue,试图掩盖罪行。
偶然的发现:一个“救命”的代码漏洞
尽管这次攻击构思精密,但最终败在了一个低级的逻辑错误上。由于恶意代码通过 .pth 启动子进程,而子进程在初始化时又会再次读取同一个 .pth 文件并触发新的子进程,这导致了指数级的递归调用,形成了所谓的“Fork Bomb”。
一名 Cursor 用户因为系统内存被瞬间撑爆而察觉到异常,这才让这场阴谋浮出水面。正如知名 AI 专家 Andrej Karpathy 所言:“如果攻击者的代码写得再好一点,这件事可能几周都不会被发现”。
应对措施与修复指南
目前,受影响的版本范围已明确,开发者应立即采取以下行动:
- 1. 版本回退与检查:确认当前使用的版本。安全版本为
litellm==1.82.6。如果你安装了 1.82.7 或 1.82.8,请务必将其视为已受感染。 - 2. 凭证轮换(关键):如果曾运行过受损版本,必须立即轮换所有可能泄露的凭证,包括但不限于 AWS/Azure/GCP 密钥、SSH 密钥、API Token 及数据库密码。
- 3. 环境清理:使用社区提供的自查脚本检查
.pth 文件、持久化后门(如 sysmon.py)以及 K8s 环境的异常连接。 - 4. 后门清除:检查并删除
~/.config/sysmon/ 下的可疑脚本,并清理对应的 systemd 服务。
LiteLLM 事件不仅是一次简单的代码投毒,更是对整个 Python 生态安全性的一次警示。它暴漏了 .pth 机制可能被滥用的风险,以及依赖链中(如 DSPy、MLflow 等 2000 多个下游包)“牵一发而动全身”的脆弱性。在 AI 时代,我们在追求开发速度的同时,必须重新审视供应链的安全防护体系。