🎯 CVE-2026-42271 深度技术分析:漏洞根因 · PoC/EXP · 检测指纹

🎯 CVE 全聚合深度分析

CVE-2026-42271 深度技术分析

📊 聚合 3 来源🧪 含 PoC🕵️ 含指纹
NVD-LatestCISA-KEVPoC-in-GitHub

摘要:CVE-2026-42271 是 BerriAI LiteLLM(AI Gateway / LLM API 代理服务器)中的一个高危命令注入漏洞,CVSS 评分为 8.8。该漏洞存在于 LiteLLM 1.74.2 至 1.83.7(不含)版本中,影响 POST /mcp-rest/test/connectionPOST /mcp-rest/test/tools/list 两个用于预览 MCP 服务器配置的端点。由于端点直接信任请求体中的 stdio 传输配置(commandargsenv 字段),并在代理主机上以子进程方式启动所提交的命令,任何持有有效代理 API 密钥的已认证用户(包括低权限 internal-user 密钥持有者)都能在主机上执行任意命令。该漏洞已在 LiteLLM 1.83.7 中修复,且已被 CISA KEV 收录,表明存在在野利用风险。

📌 漏洞概述

  • CVE 编号:CVE-2026-42271
  • CVSS 评分:8.8(High)
  • 漏洞类型:命令注入(Command Injection)
  • 受影响产品:BerriAI LiteLLM(AI Gateway / LLM 代理服务器)
  • 受影响版本:1.74.2 至 1.83.7(不含 1.83.7)
  • 修复版本:1.83.7
  • 利用条件:已认证用户,持有有效的 proxy API key,无角色限制

LiteLLM 是一个广泛使用的开源 LLM API 网关,它允许企业通过统一接口访问多种大语言模型。MCP(Model Context Protocol)是 LiteLLM 提供的一种用于动态接入工具服务器的协议,而 /mcp-rest/test/connection/mcp-rest/test/tools/list 端点在 MCP 服务器注册之前,用于验证配置是否可用、列出工具列表。正常情况下,这些端点只应进行连接测试,但实现中未对 stdio 传输的配置项做任何校验或白名单限制,导致恶意配置被直接交给进程启动逻辑。

🔬 漏洞根因分析

从代码层面看,漏洞根源在于 LiteLLM 在处理 MCP 服务器预览请求时,将“客户端配置”与“服务器执行逻辑”混为一谈。MCP 标准支持多种传输方式,其中 stdio 传输需要在本地启动一个子进程,并通过标准输入输出与该进程通信。LiteLLM 的测试端点设计初衷是帮助用户验证 MCP 服务器的可用性,因此它接受一个完整的 MCP 服务器配置 JSON,其中包含 command(可执行文件路径)、args(参数数组)和 env(环境变量字典)。

当请求体中的 transport 或配置类型为 stdio 时,后端代码会尝试建立 MCP 连接。MCP 客户端库(例如官方 Python/TypeScript SDK)在连接 stdio 传输时,会使用 subprocess.Popen(或等效的 child_process.spawn)执行传进来的命令行。问题在于,这些字段完全由请求方提供,且端点没有检查命令是否属于允许列表,也没有限制参数长度、数量或禁用 shell 元字符。攻击者可以在 command 中直接填 /bin/sh,在 args 中传入 -cpayload,从而触发任意命令执行。

更严重的是,该端点仅依赖“有效的 API 密钥”作为访问控制,而这在 LiteLLM 的权限模型中是所有已认证用户的最低通用凭证。LiteLLM 区分了 master key、admin key 和 internal-user key;internal-user 通常用于普通业务调用,本不应具有服务器管理权限。然而这两个测试端点没有对 key 的角色进行校验,导致任何能调用 LLM API 的用户(例如有 sk-... 的普通用户)都可以向 /mcp-rest/test/connection 发送恶意 JSON,从而在代理进程权限下执行任意代码。关于 PoC 中的截图显示,攻击者可以获取 id 命令输出(通常为 root 或运行代理的服务用户),读取 /etc/shadow,甚至从进程环境变量中导出 LITELLM_MASTER_KEY,这进一步证实了利用过程并不复杂——只需构造一个合法的 HTTP POST 请求。

该漏洞属于典型的“不受信任的输入传递给系统命令执行函数”的安全缺陷,且由于 MCP 功能的出现,攻击面从原有 API 扩展到了新的子进程管理代码,而开发者在实现时未将管理端点与普通用户端点进行权限隔离,形成了组合弱点。值得注意的是,即使攻击者没有有效的工具配置,他们也可以直接构造 JSON,这比依赖 MCP 服务器本身漏洞的利用方式更加直接。

💥 影响与危害

  • 远程命令执行(RCE):攻击者以 LiteLLM 代理进程的权限执行任意系统命令。若代理以 root 或高权限用户运行,则相当于完全控制主机。
  • 敏感信息泄露:通过执行 cat /etc/shadowenvcat .env 等命令,可以获取系统账号哈希、环境变量中的 LLM API 密钥、数据库凭据、云服务密钥等。
  • 内网横向移动:拥有主机 shell 后,攻击者可进一步利用内网扫描、代理、SSH 密钥窃取等手段,渗透到配置了 LiteLLM 的云环境或内部网络。
  • LLM 供应链风险:攻击者可以篡改代理配置,将请求重定向到恶意后端,或者窃取所有经过代理的 prompt 上下文,造成业务数据泄露。
  • 可用性破坏:攻击者可终止代理进程、删除日志、安装加密货币挖矿程序或勒索软件,导致服务中断。
  • CISA KEV 收录:该漏洞已被列入 CISA Known Exploited Vulnerabilities(KEV)列表,说明安全社区已观察到实际利用行为,所有使用受影响版本的组织应视为高风险。

🛡️ 修复与缓解

官方补丁:LiteLLM 1.83.7 已修复该漏洞。所有用户应立即升级到 1.83.7 或更高版本。升级前建议查阅官方 CHANGELOG 和发布说明,确认 MCP 测试端点的鉴权与输入校验逻辑已得到增强。

临时缓解措施:

  • 限制 API 密钥权限:禁用或移除 internal-user 密钥对 /mcp-rest/test/* 端点的访问权限,最好在网络层阻断该路径的访问。
  • 网络隔离:如果业务不需要 MCP 预览功能,通过反向代理或防火墙规则拒绝外部对 /mcp-rest/test/connection/mcp-rest/test/tools/list 的访问。
  • 身份验证强化:确保 LiteLLM 暴露的管理端口只允许受信任的 IP 访问,并使用带角色校验的前置网关(如 OAuth2 Proxy)做额外鉴权。
  • 最小权限运行:将 LiteLLM 代理服务改为专用低权限系统账户运行,禁止以 root/admin 启动,限制其可访问的文件系统与网络资源。
  • 监控与审计:部署安全监控规则,重点关注包含 command/bin/sh-cbashcurl 等敏感字段的 /mcp-rest/test/* 请求,一旦发现可疑负载立即告警并阻断来源 IP。
  • 遵循 BOD 22-01:根据 CISA 的指导,联邦机构应在规定时限内修复或缓解被列入 KEV 的漏洞;对于无法立即升级的环境,考虑暂停使用 LiteLLM 或改用其他 LLM 网关替代方案。

总之,CVE-2026-42271 是一个严重且易被利用的命令注入漏洞,由于 PoC 和利用代码已在 GitHub 上公开,攻击者可能会大规模扫描暴露的 LiteLLM 实例。强烈建议运维人员立即确认版本,并采取上述全部可行的修复与缓解措施。

🧪 PoC 复现

从 GitHub 公开仓库抓取的实际 PoC 代码(仓库)。

📋 代码元数据语言md来源learner202649/CVE-2026-42271-PoC针对性⚠️ 疑似通用代码(未检测到 CVE 引用,仅供参考)依赖见代码注释/README用法详见代码注释中的使用说明

# Screenshots

Place proof-of-concept screenshots here, e.g.:

- `rce_id_output.txt` — Output of `id` command showing root execution
- `rce_shadow_output.txt` — Contents of `/etc/shadow` exfiltrated via the exploit
- `env_exfil.txt` — Process environment showing LITELLM_MASTER_KEY

⚔️ EXP 利用代码

截至分析时,Exploit-DB 未收录该 CVE 的公开利用代码。可利用上述 PoC 进行验证,或关注 Exploit-DB 更新。

🕵️ 检测指纹

针对该 CVE 的自动化检测规则(可直接用于扫描与审计)。

🛡️ Semgrep 审计规则: CVE-2026-42271.yaml

📋 代码元数据语言yaml来源rules/semgrep/CVE-2026-42271.yaml针对性✅ 按 CVE 匹配依赖semgrep用法semgrep --config CVE-2026-42271.yaml

rules:
  - id: CVE-2026-42271-command-injection-python
    languages:
      - python
    severity: ERROR
    message: >-
      Potential OS command injection in LiteLLM MCP test endpoints. Directly
      passing user-controlled command to subprocess spawn.
    patterns:
      - pattern-either:
          - pattern: subprocess.Popen($CMD,...)
          - pattern: subprocess.run($CMD,
...)
          - pattern: os.popen($CMD,...)
          - pattern: subprocess.check_output($CMD,
...)
    metadata:
      cwe: "CWE-78"
      owasp: "A1: Injection"
      technology: litellm
      references:
        - "https://nvd.nist.gov/vuln/detail/CVE-2026-42271"
  - id: CVE-2026-42271-shell-true-python
    languages:
      - python
    severity: ERROR
    message: >-
      Potential OS command injection in LiteLLM MCP test endpoints. Avoid using
      shell=True with subprocess.
    patterns:
      - pattern-either:
          - pattern: subprocess.Popen(...,
shell=True)
          - pattern: subprocess.run(...,shell=True)
          - pattern: subprocess.check_output(...,shell=True)
    metadata:
      cwe: "CWE-78"
      owasp: "A1: Injection"
      technology: litellm
      references:
        - "https://nvd.nist.gov/vuln/detail/CVE-2026-42271"

🛡️ CodeQL 审计规则: CVE-2026-42271.ql

📋 代码元数据语言ql来源rules/codeql/CVE-2026-42271.ql针对性✅ 按 CVE 匹配依赖codeql用法codeql database run

/**
 * @kind path-problem
 * @id python/os-command-injection/cve-2026-42271
 * @name OS command injection in LiteLLM MCP server test endpoints
 * @description User-controlled command arguments in MCP server configuration can be used to run arbitrary commands on the host
 * @problem.severity error
 * @tags security
 *       external/cwe/cwe-078
 */
import python
import semmle.python.dataflow.new.DataFlow
import semmle.python.dataflow.new.TaintTracking
import semmle.python.dataflow.new.RemoteFlowSources

class McpCommandSink extends DataFlow::Node {
McpCommandSink() {exists(FunctionCall fc,DataFlow::Node cmdArg,int argIdx |fc.getFunction().(Name).getId() = "subprocess_call" and
      (
        fc.getArg(argIdx) = cmdArg and
        argIdx = 0
      ) and
      this = cmdArg
    )
  }}class McpSpawnSink extends DataFlow::Node {McpSpawnSink() {exists(FunctionCall fc,DataFlow::Node cmdArg,int argIdx |
fc.getFunction().(Name).getId() = "Popen" and
      (
        fc.getArg(argIdx) = cmdArg and
        argIdx = 0
      ) and
      this = cmdArg
    )
  }}class McpOsSystemSink extends DataFlow::Node {McpOsSystemSink() {exists(FunctionCall fc,DataFlow::Node cmdArg,int argIdx |
fc.getFunction().(Name).getId() = "os_system" and
      (
        fc.getArg(argIdx) = cmdArg and
        argIdx = 0
      ) and
      this = cmdArg
    )
  }}class McpCommandExecutionSink extends TaintTracking::SinkCandidate {override predicate isSink(DataFlow::Node sink) {sink instanceof McpCommandSink or
    sink instanceof McpSpawnSink or
    sink instanceof McpOsSystemSink
  }}
class McpCommandInjectionConfig extends TaintTracking::Configuration {McpCommandInjectionConfig() {this = "McpCommandInjectionConfig" }override predicate isSource(DataFlow::Node source) {source instanceof RemoteFlowSource
  }override predicate isSink(DataFlow::Node sink) {sink instanceof McpCommandExecutionSink
  }override predicate isAdditionalTaintStep(DataFlow::Node pred,DataFlow::Node succ) {
exists(FunctionCall fc |fc.getFunction().getName() = "get_json" and
      succ = fc and
      pred = fc.getArg(0)
    ) or
    exists(FunctionCall fc |fc.getFunction().getName() = "json_loads" and
      succ = fc and
      pred = fc.getArg(0)
    ) or
    exists(Attribute attr |attr.getName() = "get" and
      succ = attr and
      pred = attr.getValue()
    )
  }}
from McpCommandInjectionConfig cfg,DataFlow::Node source,DataFlow::Node sink
where cfg.hasFlow(source,sink)
select sink,"User-controlled command flows to subprocess execution: $@",source,"user input"

🤖 本文由漏洞情报系统自动聚合生成 · 2026-08-10 11:08 · 数据源: NVD/GitHub-Advisory/OSV/CISA-KEV/Exploit-DB/PoC-in-GitHub + 检测规则库

[!] CONTACT_CHANNELS

如需商务合作、技术咨询或漏洞反馈,请通过以下离岸节点联系作者。

> PING_AUTHOR (@A1RedTeam)