2026 年 3 月发生的 LiteLLM 供应链攻击事件揭示了 Python 生态系统供应链安全的深层脆弱性。本文不从事件响应角度重复叙述时间线,而是聚焦于恶意代码本身的技术逆向分析,深入剖析.pth 文件注入机制、凭证收集逻辑、通信协议与持久化设计,为安全研究人员提供可操作的代码层解读。

.pth 文件注入的技术原理

LiteLLM 攻击的核心 payload 利用了 Python 语言中一个少为人知但危险的功能特性:.pth 文件的自定义代码执行机制。根据 Python 官方文档,自 Python 3.5 版本起,位于 site-packages 目录下的.pth 文件中,以 "import"(import 后跟空格或 Tab)开头的行会被 Python 解释器作为代码执行,而非仅仅作为路径配置。

这一机制的设计初衷是允许第三方包在安装时动态添加搜索路径,但攻击者将其改造为隐蔽的持久化手段。在 LiteLLM 恶意版本中,攻击者创建了名为litellm_init.pth的文件并植入 site-packages 目录。该文件的首行以import开头,触发 Python 解释器在任意模块导入时自动执行其中的恶意代码。值得注意的是,这种持久化方式并不依赖特定的应用启动触发 —— 任何 Python 进程的创建都会激活.pth 文件,这意味着即使用户仅是运行一个简单的脚本或导入其他无关模块,恶意代码也会同步执行。

从检测角度而言,.pth 文件的监控长期处于安全工具的盲区。传统 EDR 和 SIEM 规则往往聚焦于注册表修改、服务创建或计划任务等传统持久化点,而对 Python 运行时环境的特殊文件机制缺乏感知。DFIR 社区的研究表明,大多数自动化枚举脚本默认不会检查 site-packages 目录下的.pth 文件变化,这使得该技术成为攻击者偏爱的隐形持久化通道。

凭证收集与数据窃取逻辑

恶意代码的收集模块设计精密,覆盖了现代云原生环境中几乎所有类型的敏感凭据。代码首先针对 SSH 私钥(通常位于~/.ssh/ 目录)、环境配置文件(.env)、云服务提供商凭证(AWS、GCP、Azure)进行定向扫描。针对 Kubernetes 环境,攻击者特别关注集群配置文件和 ServiceAccount 令牌,这些凭据通常挂载在 Pod 的文件系统中,可通过读取/var/run/secrets/kubernetes.io/路径获取。

数据库连接凭据同样是重点目标,代码会遍历常见配置文件路径搜索 MySQL、PostgreSQL、MongoDB 等数据库的连接字符串。此外,Git 配置文件(.gitconfig)、Shell 历史记录(.bash_history、.zsh_history)以及加密货币钱包文件也被纳入收集范围。收集脚本还会主动执行命令转储当前进程的环境变量,并尝试访问云平台的实例元数据服务(IMDS)和容器凭证端点,这些接口在大多数云环境中默认开放且缺乏认证。

这种全维度收集策略反映了攻击者对云原生技术栈的深刻理解 —— 现代 AI 基础设施高度依赖 Kubernetes 和多云部署,任何单一凭据的泄露都可能为攻击者提供横向移动的跳板。

外传协议与加密机制

窃取的凭证数据并非以明文形式传输。攻击者采用混合加密架构:使用 AES-256-CBC 算法对数据 payload 进行对称加密,加密密钥则通过 4096 位 RSA 公钥进行非对称加密后附加在密文头部。这种双层加密设计确保了即使通信流量被截获,攻击者也只有持有对应私钥才能解密获取明文凭据。

加密完成后的数据被打包成 tar 格式的归档文件,随后通过 HTTP POST 请求发送至models.litellm.cloud域名。该域名伪装为合法的 LiteLLM 基础设施域名,但实际上并非项目官方所有,这种域名欺骗手法增加了事件分析的混淆程度。从网络层监控角度,检测异常的外向连接 —— 特别是发往非预期域名的 HTTP POST 请求 —— 是识别此类攻击的关键指标。

横向移动与集群渗透

LiteLLM 恶意代码的横向移动能力针对 Kubernetes 环境进行了专门优化。当检测到存在 Kubernetes ServiceAccount 令牌时,代码会遍历集群所有命名空间并批量读取 Secrets 资源。更进一步,攻击者尝试在 kube-system 命名空间的每个节点上创建特权 Pod(使用 alpine:latest 镜像),并挂载宿主机的根文件系统。这种手法可直接获取节点级别的代码执行权限,实现对整个集群的完全控制。

值得注意的是,攻击者的横向移动脚本针对 AI 基础设施做了定制化适配 ——LiteLLM 作为 LLM 代理库,通常部署在需要访问多种云资源和 API 密钥的环境中,这使得攻击收益远高于普通应用。

持久化后门设计

为确保失陷主机重启后仍可继续控制,攻击者部署了多层持久化机制。主后门文件被写入~/.config/sysmon/sysmon.py,并配置 systemd 用户服务(~/.config/systemd/user/sysmon.service)实现开机自启。在 Kubernetes 环境中,相同的持久化逻辑通过之前创建的特权 Pod 同步部署。

发现该攻击的过程具有偶然性:恶意.pth 文件在每次 Python 解释器启动时都会被触发,当主进程 fork 子进程时,子进程同样会读取.pth 文件并再次触发 payload 执行。这种递归触发形成了一个类似 fork bomb 的指数级进程增殖,最终导致主机资源耗尽崩溃。正是这个实现缺陷使得攻击提前暴露,否则恶意代码可能长期隐匿运行。

防御与检测建议

针对.pth 文件持久化机制的检测,建议安全团队采取以下措施:首先,在 SIEM 或 EDR 中建立 site-packages 目录的变更监控策略,告警新增或修改的.pth 文件;其次,部署 Python 运行时环境的应用行为监控,识别异常的网络连接和文件系统访问模式;再次,对发往非预期域名的凭证类数据外传进行深度包检测;最后,在 Kubernetes 环境中严格限制 Pod 权限,禁止在 kube-system 命名空间创建特权容器,并对 ServiceAccount 令牌的生命周期实施严格管理。

供应链安全层面,建议组织建立 PyPI 包的哈希校验机制,对比发布包与 GitHub 源码仓库的差异,同时实施依赖锁定策略防止自动升级到恶意版本。


参考资料