LLM应用程序使用第三方插件进行网页浏览、代码执行或数据库访问。攻击者攻破插件的更新流水线,推送恶意版本。下一次LLM调用该插件时,恶意代码会在应用环境中执行。
关键技巧:插件供应链入侵——类似于软件供应链攻击。
现实案例
JetBrains Marketplace恶意插件活动
JetBrains 市场:AI 插件活动窃取 LLM API 密钥——实验室空间
攻击链概览
恶意插件伪装成合法的 AI 编程助手(如 DeepSeek AI Assist、CodeGPT AI Assistant),在用户将 API 密钥粘贴到设置面板并点击“Apply”时,立即捕获密钥并通过未加密的 HTTP POST 发送到攻击者控制的服务器。整个攻击链可以概括为以下几步:
- 密钥捕获:用户在插件设置中粘贴 API Key。
- 针对性验证:插件代码对密钥格式进行校验,只对符合特定模式的密钥执行后续操作。
- 数据传输:通过未加密的 HTTP POST 将密钥发送到硬编码的 C2 端点。
- TLS 抑制:通过自定义 X509TrustManager 禁用 TLS 证书验证,避免 IDE 抛出安全警告。
X509TrustManager 如何禁用 TLS 验证
这是整个攻击链中最隐蔽的一环。Java 的 X509TrustManager 是负责验证 SSL/TLS 证书的核心接口。正常情况下,客户端与服务器建立 HTTPS 连接时,checkServerTrusted() 方法会被调用,用于验证服务器证书是否由受信任的 CA 签发、是否在有效期内、是否匹配主机名等。
恶意插件通过 JVM 级别的全局替换,实现了一个“信任一切”的 TrustManager。其核心代码模式通常如下:
java
X509TrustManager trustAll = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) {
// 空实现,不做任何校验
}
public void checkServerTrusted(X509Certificate[] chain, String authType) {
// 空实现,不做任何校验 —— 这就是"信任一切"的关键
}
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
};
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new TrustManager[]{trustAll}, new SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
当 checkServerTrusted() 被实现为空方法时,任何服务器证书都会被无条件接受,包括自签名证书、过期证书、主机名不匹配的证书等。这意味着:
- 即使 C2 服务器使用自签名证书或根本没有有效的证书,HTTPS 连接也不会抛出
SSLHandshakeException; - IDE 的调试器、日志系统或安全插件不会产生任何 TLS 相关的警告或异常,攻击行为在运行时完全“静默”。
此外,部分插件还将该 TrustManager 设置为 JVM 全局默认值,这意味着整个 IDE 进程内所有 HTTPS 连接都会继承这一“信任一切”的策略,而不仅仅是恶意插件自身的连接。这种全局污染使得其他插件或 IDE 组件的正常安全校验也被一并绕过。
LiteLLM 供应链攻击
LiteLLM 供应链攻击完整拆解:从 Trivy 失陷到 PyPI 投毒
攻击者 fork Trivy ↓ 提交 PR #10252,触发 pull_request_target ↓ Trivy 高权限工作流运行了攻击者代码 ↓ 高权限令牌被偷 ↓ 攻击者控制 Trivy 仓库 ↓ 重写 75 个 Trivy 版本标签,指向恶意代码 ↓ LiteLLM 的 CI/CD 动态安装 Trivy ↓ LiteLLM 拉到并执行了恶意 Trivy ↓ 恶意 Trivy 扫描环境变量,偷走 PYPI_PUBLISH_PASSWORD ↓ 攻击者获得 LiteLLM 的 PyPI 发布权限 ↓ 向全球用户发布恶意 LiteLLM 版本
供应链蠕虫针对具有 LLM 扫描规避和凭证清除守护进程的 AI/ML 包
Shai-Hulud/Hades PyPI 供应链蠕虫针对具有 LLM 扫描规避和凭证清除恶魔的 AI/ML 包 |eyeon.ai
1. 投递:用被盗凭证发布恶意包
- 攻击者(UNC6780/TeamPCP)使用被盗的 PyPI 凭证,在 2026 年 6 月 8 日上传了 26+ 个恶意包。
- 目标明确:AI/ML 和生物信息学工具。
- 其中包含
langchain-core-mcp,这是对真实包langchain-mcp的域名仿冒(typosquatting),专门针对 LangChain 用户。 - 恶意包版本号看起来正常,容易被开发者误装。
2. 触发:.pth 文件在解释器启动时自动执行
- 恶意包会释放一个
\*-setup.pth文件。 - Python 的
site模块会在每次 Python 解释器启动时自动执行.pth文件中的代码,这发生在任何import之前。 - 效果:只要包被安装,无论是否导入,恶意代码都会在后台静默运行。卸载重装后仍可能存活。
3. 载荷下载与执行:Bun + 混淆 JS
.pth钩子首先从 GitHub 下载 Bun JavaScript 运行时到一个临时目录。- 然后执行一个高度混淆的
_index.js恶意脚本。 - 这一步把攻击载荷从 Python 环境转移到 JavaScript 运行时,增加检测难度。
4. 凭证窃取:扫描进程内存
_index.js的核心任务是读取进程内存来抓取凭证:- Linux:
/proc/{pid}/mem - macOS:Mach API
- Windows:
ReadProcessMemory
- Linux:
- 这种内存扫描方式可以绕过文件级加密存储,即使凭证没有落盘也能被窃取。
- 目标覆盖 14 个 AI/云/DevOps 系统,重点包括:
- MCP 服务器配置
- Anthropic/OpenAI API 密钥
- AI 编码代理令牌
5. 加密外传:AES + RSA,发到 GitHub C2
- 窃取到的数据使用 AES-256-GCM + RSA-2048 加密。
- 然后外传到攻击者控制的 GitHub 仓库。
- 外泄仓库的命名特征:
stygian-cerberus-*和tartarean-charon-*。
6. 自我传播:用偷来的凭证继续投毒
- 蠕虫利用窃取到的凭证,将自身发布到更多包中,实现横向传播。
- 这意味着攻击面会从最初的 26+ 个包迅速扩大,形成连锁感染。
7. 反制:gh-token-monitor 守护进程
- 攻击者植入一个持久化守护进程
gh-token-monitor。 - 该进程监控被盗凭证的状态:一旦检测到凭证被轮换(重置),就威胁采取破坏性行动。
- 这颠覆了标准事件响应流程:传统做法是“先隔离,后轮换”,但现在轮换可能触发攻击者破坏数据。
- 正确应对:先隔离受影响系统,再轮换凭证。
8. 规避:提示注入欺骗 LLM 安全扫描器
- 恶意载荷中嵌入了提示注入文本。
- 目的不是攻击 LLM 应用,而是欺骗基于 AI 的安全分析工具,使其误判为无害或触发安全拒绝,从而绕过 AI 辅助防御。
- 这标志着攻击者开始主动攻击安全防御工具本身。