Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
supernote-obsidian-plugin-PoC — PoC — 通过 Supernote Obsidian 插件中的恶意设备同步进行路径遍历(GHSA-3gx3-r874-5pp4,CVE-2026-86999,CVSS 5.6)。 | Kitploit
工具/GitHubGitHub/squeeze440/supernote-obsidian-plugin-poc
漏洞分析漏洞利用Web应用程序漏洞利用安全虚拟化渗透测试论文与研究
GitHubsqueeze440/supernote-obsidian-plugin-poc

supernote-obsidian-plugin-PoC

PoC — 通过 Supernote Obsidian 插件中的恶意设备同步进行路径遍历(GHSA-3gx3-r874-5pp4,CVE-2026-86999,CVSS 5.6)。

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
查看仓库
7天前尚未审核
分享

摘要

CVE 状态: 已申请,待分配。此发现已发布为 GHSA-3gx3-r874-5pp4。在 CVE 分配后,此仓库将重命名为 CVE-YYYY-NNNNN-supernote-obsidian-plugin-PoC,并且此横幅将替换为 CVE 链接。

研究员Dostxodjayev Abdullox (@squeeze440)
安全公告GHSA-3gx3-r874-5pp4
CVSS 3.15.6(中危)
弱点CWE-22, CWE-73

摘要

Supernote(非官方)Obsidian 插件(philips/supernote-obsidian-plugin)v2.9.1 的设备自动同步功能中存在路径遍历漏洞,允许恶意或流氓的“Supernote”设备(或冒充已配对设备 IP 的路径上/局域网内攻击者)通过设备目录列表响应中精心构造的 uri 字段,使受害者的 Obsidian 客户端在桌面进程可写入的任意位置写入任意新文件——包括在配置的同步文件夹之外以及保险库本身之外。

产品

philips/supernote-obsidian-plugin(“Supernote(非官方)”),一个 Obsidian.md 社区插件,通过设备本地的“浏览和访问”HTTP 服务器(http://<device-ip>:8089,无身份验证,这是设备功能的设计使然)将物理 Supernote 电子墨水设备的笔记同步到保险库中。

测试版本

  • 插件:v2.9.1,提交 48db5bf4dcfb100632c84699c830c1309da1abb9
  • 子模块 supernote-typescript:提交 195415b3a1f74147...(本身不涉及——该漏洞完全存在于插件自身的同步规划代码中)
  • 宿主应用:Obsidian 桌面版 1.13.4(真实二进制文件,动态测试)

估计的 CVSS v3.1

5.6 中危 — CVSS:3.1/AV:A/AC:H/PR:N/UI:R/S:C/C:N/I:H/A:N

  • AV:A — 设备的 HTTP 服务器为明文、无身份验证,且仅通过裸 IPv4 地址配置(IP_VALIDATION_PATTERN,src/settings.ts:6);以“设备”身份访问它需要局域网相邻的网络位置(流氓 AP、ARP 欺骗或声称拥有该 IP),而非任意远程访问。
  • AC:H — 利用取决于攻击者在受害者插件与 directConnectIP:8089 通信时已占据该网络位置;这不是一次性远程触发。
  • UI:R — 需要受害者在指向攻击者控制的端点时运行“立即同步 supernote 笔记”(或已启用自动同步开关)。
  • S:C — 易受攻击的组件是保险库范围内的 Obsidian 插件;写入完全落在保险库之外,位于底层宿主文件系统上,这是不同的安全范围。
  • C:N — 这是仅写入的原语;没有任何内容被读回给攻击者。
  • I:H — 攻击者控制的字节落在攻击者选择的路径和攻击者选择的文件名上。有限的注意事项:writeBinaryAt()(src/syncEngine.ts:40-47)仅对插件自身同步清单中尚未跟踪的路径采用创建分支,并且 Obsidian 的 Vault.createBinary() 本身拒绝静默覆盖在解析路径上已物理存在的文件(经验证实——见 PoC)——因此这是“在任意位置植入新文件”,而非“覆盖任何现有文件”。
  • A:N — 未证明有可用性影响。

详情

runDeviceSync()(src/syncEngine.ts:100-196)通过 scanDeviceSupernoteTree()(src/FileListModal.ts:53-68)列出已配对设备的文件,该函数递归设备的 HTTP 目录列表,并保留任何 name 匹配 /\.(note|spd)$/i 的条目(src/FileListModal.ts:46,63)。每个条目的 uri 字段——设备返回的同一 JSON 对象中一个独立的、可单独控制的字符串——从未针对 name 或任何其他内容进行验证。

该原始 uri 随后被直接送入 deviceUriToVaultPath()(src/deviceSync.ts:153-161):

root@kitploit:~
const INVALID_FILENAME_CHARS = /[\\:*?"<>|]/g;   // deviceSync.ts:144

export function deviceUriToVaultPath(syncFolder: string, deviceUri: string): string {
    const segments = deviceUri
        .split('/')
        .filter((s) => s.length > 0)
        .map((s) => s.replace(INVALID_FILENAME_CHARS, '_'));

    const cleanRoot = syncFolder.replace(/^\/+|\/+$/g, '');
    return cleanRoot ? `${cleanRoot}/${segments.join('/')}` : segments.join('/');
}

INVALID_FILENAME_CHARS 会剥离 \ : * ? " < > |,但从不剥离或拒绝 .. 路径段。设备 uri 为 /../../PWNED.txt 时原样保留,并被拼接到配置的同步文件夹(默认 "Supernote sync")上,产生 vaultPath = "Supernote sync/../../PWNED.txt"。

syncEngine.ts:128 从列表的原始 uri 计算此 vaultPath,然后 ensureFolder()/writeBinaryAt()(syncEngine.ts:146-148、21-47)将其直接传递给 app.vault.getAbstractFileByPath() / createBinary() / modifyBinary(),没有任何遍历检查。Obsidian 自身的路径解析随后针对磁盘上的真实保险库目录规范化 .. 段,使写入落在同步文件夹之上——并且,如果有足够的 ../ 段,则完全落在保险库根目录之上,落到宿主文件系统上,处于操作系统用户自身的权限范围内。

同类检查:此代码库中所有其他保险库写入汇点(src/main.ts——屏幕镜像捕获、PDF/markdown 导入、“附加到笔记”、src/FileListModal.ts:245-246 中的 DownloadListModal)都通过 Obsidian 自身的 app.fileManager.getAvailablePathForAttachment(file.name) 构建其目标路径,该方法仅使用设备的 name 字段,无法以这种方式利用。较新的自动同步功能中的 deviceUriToVaultPath() 是唯一一个改为从设备的 uri 字段手工拼接路径的汇点,也是跳过了 .. 清理的那个——一个典型的“所有同类都检查了,唯独这个没有”的案例。

插件自身的设置 UI 声明:“同步命令绝不会写入此文件夹之外的任何位置”(src/settings.ts,同步文件夹描述)——此 PoC 直接证伪了该保证。

概念验证

针对真实、未修改的 Obsidian 1.13.4 桌面二进制文件(Xvfb + fluxbox + xdotool + scrot)动态端到端确认,运行插件实际编译的 main.js——没有对插件代码进行任何模拟。

  1. 从源代码构建插件(./scripts/build)并将其加载到全新的测试保险库中(Supernote (Unofficial) v2.9.1,通过“信任作者并启用插件”启用)。
  2. 将插件设置 Supernote IP address 设为 127.0.0.1,将 Sync folder 保留为默认值 Supernote sync。
  3. 在 127.0.0.1:8089 上搭建一个单文件 Node 模拟设备“浏览和访问”服务器,模拟恶意/流氓设备。其目录列表返回:
    root@kitploit:~
    {"name":"Quick notes.note","size":61,"date":"2026-07-31 00:00:00",
     "uri":"/../../PWNED_BY_DEVICE_SYNC.txt","extension":"note","isDirectory":false}
    
    (name 通过 .note 扩展名过滤器;uri 携带遍历。)任何 GET 都以 200 和文件字节响应——真实 HTTP 客户端在请求路径到达网络之前会规范化出站请求路径中的 ..(RFC 3986),这在此处无关紧要,因为易受攻击的代码是从原始 JSON 字符串计算写入路径,而非从规范化后的请求 URL。
  4. 运行命令面板操作 “Supernote (Unofficial): Sync supernote notes now”。
  5. 结果:一个新文件 PWNED_BY_DEVICE_SYNC.txt,包含攻击者的字节,被创建在保险库根目录的上一级目录(testvault/ 的同级,完全在保险库之外)。插件自身的 data.json 逐字记录了计算出的路径:"vaultPath": "Supernote sync/../../PWNED_BY_DEVICE_SYNC.txt"。

证据(真实捕获,~/engagements/supernote-obsidian-plugin/evidence/):

  • 01-vault-escape-file-write.png — 真实终端:ls -la testvault/ PWNED_BY_DEVICE_SYNC.txt 显示该文件作为保险库目录的同级,以及通过 cat 显示其攻击者控制的内容。
  • 02-plugin-data-json-vaultpath.png — 插件自身持久化的同步状态文件记录 "vaultPath": "Supernote sync/../../PWNED_BY_DEVICE_SYNC.txt"。
  • 03-plugin-settings-security-claim.png — 插件设置 UI 声称同步命令“绝不会写入此文件夹之外的任何位置”。

影响

能够以受害者配置的 Supernote 设备身份响应的攻击者(局域网相邻:流氓 AP、ARP 欺骗或声称拥有设备 IP)可以使受害者的 Obsidian 客户端在桌面进程可写入的任意文件系统路径创建新的、攻击者控制的文件——在保险库内(例如 .obsidian/plugins/<new-id>/ 下的全新文件,为进一步滥用插件信任奠定基础)或完全在其之外(例如 ~/.config/autostart/*.desktop、新的 crontab drop-in,或任何其他新文件——而非覆盖——足以获得执行或持久性的位置)。它无法静默覆盖在解析路径上已存在的文件(在这种情况下 Obsidian 的 createBinary 抛出“File already exists”,经验证实),这将该原语限制为净新文件植入,而非通用覆盖。

弱点

  • CWE-22:对路径名的限制不当导致受限目录遍历(“路径遍历”)
  • CWE-73:文件名或路径的外部控制(设备提供的 uri 直接决定磁盘上的目标位置)

修复

在 deviceUriToVaultPath()(src/deviceSync.ts:153-161)中,在拆分 deviceUri 后拒绝或剥离 ..(以及空/仅 .)路径段,例如:

root@kitploit:~
const segments = deviceUri
    .split('/')
    .filter((s) => s.length > 0 && s !== '.' && s !== '..')
    .map((s) => s.replace(INVALID_FILENAME_CHARS, '_'));

此外,scanDeviceSupernoteTree()(src/FileListModal.ts:63)应验证列表条目的 uri 与其 name 一致(例如 uri 以相同文件名结尾),而非独立信任这两个字段——这是代码库中其他地方已隐式依赖的同类防御,那些地方仅通过 getAvailablePathForAttachment() 从 name/basename 构建路径。

致谢

Dostxodjayev Abdullox

报告渠道

此仓库中不存在 SECURITY.md。GitHub 私密漏洞报告已确认对 philips/supernote-obsidian-plugin 启用(gh api repos/philips/supernote-obsidian-plugin/private-vulnerability-reporting --jq .enabled → true;此前发布的安全公告为 0)。适用标准 GHSA 流程:https://github.com/philips/supernote-obsidian-plugin/security/advisories/new。

下载工具