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

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

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

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

工具目录

分类

查看所有分类
Loading categories
CVE-2025-68621 — CVE-2025-68621(Trilium Notes同步登录的时序攻击)的教育性PoC与分析。演示了通过网络时序侧信道恢复HMAC哈希,并包含了根本原因、修复方法及缓解措施详情。 | Kitploit
工具/GitHubGitHub/sivaadityacoder/cve-2025-68621
漏洞分析漏洞利用Web安全密码学论文与研究学习与教育
GitHubsivaadityacoder/cve-2025-68621

CVE-2025-68621

CVE-2025-68621(Trilium Notes同步登录的时序攻击)的教育性PoC与分析。演示了通过网络时序侧信道恢复HMAC哈希,并包含了根本原因、修复方法及缓解措施详情。

查看仓库
3个月前尚未审核

最受欢迎

查看全部 →

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

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2025-68621 — Trilium Notes 对 /api/login/sync 的时序攻击

严重性: 高 (CVSS 7.4)
受影响软件: TriliumNext/Trilium < 0.101.0
漏洞类型: CWE-208 – 可观察的时序差异
修复版本: Trilium 0.101.0 (PR #8129)
发布日期: 2026-02-06 | 保留日期: 2025-12-19


目录

  1. 我的分析方法
  2. 根本原因
  3. 影响
  4. 修复方案
  5. 关键要点
  6. 时间线
  7. 参考资料

我的分析方法

什么是 Trilium Notes?

Trilium Notes 是一款开源、跨平台、层次化的笔记应用程序,专为构建大型个人知识库而设计。它支持:

  • 自托管服务器,多个客户端可与之同步
  • 丰富的笔记类型(文本、代码、画布、图表)
  • 强大的脚本 API

同步功能允许 Trilium 客户端向 Trilium 服务器进行身份验证,以便笔记在设备间保持同步。该同步端点正是 CVE-2025-68621 的入口点。

什么是时序攻击?

时序攻击是一种旁路攻击,攻击者通过测量系统处理不同输入所需的时间来获取秘密信息。

经典例子是字符串比较:

root@kitploit:~
"correct_password" !== "aorrect_password"   → 在第 0 位失败 → 快速  
"correct_password" !== "cXrrect_password"   → 在第 1 位失败 → 稍慢  
"correct_password" !== "correct_password"   → 完全匹配 → 最慢  

大多数编程语言在比较字符串时逐字符进行,并且一旦发现不匹配就立即停止(提前退出)。这意味着:

  • 匹配第一个字节的猜测比立即不匹配的猜测耗时略长。
  • 通过发送数千个猜测并平均响应时间,攻击者可以统计确定哪个字节是正确的——逐位进行——直到恢复完整秘密。

修复方法是使用常量时间比较函数,该函数无论在哪里出现不匹配,始终检查每个字节。

漏洞是如何发现的

该漏洞通过对 Trilium 认证逻辑的手动代码审查发现。研究人员检查了 apps/server/src/routes/api/login.ts 中的同步登录流程,并在 loginSync() 函数(约第 111 行)中注意到以下模式:

root@kitploit:~
const documentSecret = options.getOption("documentSecret");
const expectedHash   = utils.hmac(documentSecret, timestampStr);
const givenHash      = req.body.hash;

if (expectedHash !== givenHash) {          // ← 有漏洞的行
    return [400, { message: "Sync login credentials are incorrect..." }];
}

危险信号是使用 JavaScript 内置的 !== 运算符比较 HMAC 哈希。!== 运算符不是常量时间——一旦发现不同字符就退出。由于比较是在纯字符串上进行的(未使用密码学安全的比较函数),响应时间会泄漏攻击者猜测中有多少个前导字节是正确的。

研究人员随后问道:

“这种微小的时序差异在网络中能否被放大到足以恢复完整的 44 字符 Base64 编码 HMAC 哈希?”

答案是可以——通过足够多的重复测量和统计数据分析,信号可以超越噪声。

攻击算法

当 Trilium 客户端想要同步时,它会使用 JSON 主体调用 POST /api/login/sync:

root@kitploit:~
{
  "timestamp":   "2025-12-19T10:00:00.000Z",
  "syncVersion": 34,
  "hash":        "<HMAC-SHA256 of documentSecret + timestamp, Base64-encoded>"
}

逐字节恢复的工作原理如下:

root@kitploit:~
对于位置 = 0 到 43:
    对于字符集(A-Z,a-z,0-9,+,/,=)中的每个候选字符 c:
        发送 SAMPLES 个请求,hash = known_prefix + c + 填充
        记录平均响应时间
    最佳字符 = 平均时间最高的候选字符
    将该字符追加到 known_prefix

经过 44 次迭代(每个 Base64 字符一次),完整的 44 字符 HMAC 哈希被恢复。

实际需求:

  • 超过 100 000 次 HTTP 请求(50 个样本 × 65 个字符集字符 × 44 个位置 ≈ 143 000)
  • 超过 1 000 个不同的源 IP 地址(由于 Trilium 的速率限制,需要轮换代理或僵尸网络)
  • 攻击者与服务器之间的低网络抖动(LAN 或稳定的云连接效果最佳)
  • 高精度计时器(Python 中的 time.perf_counter() 提供纳秒分辨率)

概念验证

参见 poc.py 获取带有完整注释的 Python PoC。

PoC 功能简要总结:

  1. 遍历 HMAC 哈希的所有 44 个 Base64 字符位置。
  2. 对于每个位置,尝试 Base64 字符集(A–Z,a–z,0–9,+,/,=)中的每个字符。
  3. 为每个候选字符发送 50 次 HTTP POST 请求到 /api/login/sync,并测量中位响应时间。
  4. 选择中位响应时间最高的候选字符作为正确字符。
  5. 恢复所有 44 个字符后,使用恢复的哈希进行身份验证。

免责声明: 本 PoC 仅供教育目的和负责任的安研使用。请勿对非您拥有或未经明确书面许可的系统使用。


根本原因

JavaScript 的 !==(和 ===)运算符执行字典序、提前退出的比较。在 apps/server/src/routes/api/login.ts 中有漏洞的行:

root@kitploit:~
if (expectedHash !== givenHash) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

提前退出行为为每个匹配的字节创建了可测量的时序差异:

每个额外匹配的字节会多花费微小的 CPU 时间 δ。在数千个样本中,猜测“正确字节 N”的平均响应时间比猜测“错误字节 N”的响应时间明显更长,从而泄漏足够的信息来逐字符恢复完整的 HMAC 哈希。

CVSS 得分明细

向量字符串: CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N


影响

成功利用后,攻击者将获得:

  • 完整的读取权限,访问所有笔记,包括加密的笔记元数据
  • 完整的写入权限——攻击者可以创建、修改或删除笔记
  • 持久的访问权限——恢复的哈希可重复使用(在时间戳窗口内)

对于在 Trilium 知识库中存储敏感个人数据(密码、私密文档、日记)的用户来说,这尤其严重。


修复方案

修复方案将非恒定时间的 !== 比较替换为 Node.js 内置的 crypto.timingSafeEqual():

之前(有漏洞):

root@kitploit:~
if (expectedHash !== givenHash) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

之后(安全):

root@kitploit:~
import * as crypto from "crypto";

const expectedBuffer = Buffer.from(expectedHash);
const givenBuffer    = Buffer.from(givenHash ?? "");

if (expectedBuffer.length !== givenBuffer.length ||
    !crypto.timingSafeEqual(expectedBuffer, givenBuffer)) {
    return [400, { message: "Sync login credentials are incorrect..." }];
}

crypto.timingSafeEqual() 始终比较每个字节,因此执行时间不依赖于匹配的字节数。时序信号消失。

参见 vulnerable.ts 和 fix.ts 以获取并排代码示例。

如何更新

如果您运行的是自托管的 Trilium 服务器,请立即升级到 0.101.0 或更高版本。

root@kitploit:~
# Docker 示例
docker pull zadam/trilium:0.101.0

关键要点

  1. 切勿使用 === / !== 比较机密。 JavaScript 的相等运算符不是恒定时间的。任何使用 === / !== 对 HMAC、令牌或密码的比较都是潜在的时序预言机。

  2. 在 Node.js 中始终使用 crypto.timingSafeEqual()(或您语言/运行时的等效方法)比较加密值。这是专为此任务设计的标准 API。

  3. 时序攻击在网络上是真实存在的。 虽然纳秒级差异在互联网上似乎不可能检测到,但统计技术和足够样本可以从嘈杂的测量中提取出清晰的信号——尤其是在低抖动环境中。

  4. 仅靠速率限制不足以缓解。 即使每个 IP 有速率限制,攻击者通过轮换代理或僵尸网络仍可积累足够样本来利用时序差异。

  5. HMAC 验证应与密码比较受到同等关注。 HMAC 哈希是机密。应像处理任何机密值比较那样,假设时序旁路可能被利用。

  6. 对加密模式的代码审查至关重要。 该漏洞通过手动审查发现——一行看似无害的代码却带来严重的安全隐患。专门的加密/安全审计有助于及早发现此类问题。


时间线

日期事件

参考资料


本仓库根据负责任的披露原则维护,仅供教育和研究目的。

下载工具
猜测 vs. 期望比较的字节数时间
错误字节 01~T
正确字节 0,错误字节 12~T + δ
正确字节 0–1,错误字节 23~T + 2δ
………
全部 44 字节正确44~T + 43δ
指标值原因
基础分7.4 高
攻击向量网络 (N)可通过互联网利用
攻击复杂度高 (H)需要大量请求 + 稳定的时序
所需权限无 (N)无需账户
用户交互无 (N)受害者无需任何操作
范围不变 (U)仅影响 Trilium 服务器
机密性高 (H)完整笔记库可读
完整性高 (H)攻击者可写入/修改笔记
可用性无 (N)不包含拒绝服务组件
2025-12-19CVE-2025-68621 由 GitHub Security 保留
2025-12-21修复 PR #8129 提交
2025-12-25PR 合并;Trilium 0.101.0 发布
2026-02-06CVE 公开发布
2026-02-09CISA ADP 丰富信息添加
资源链接
GitHub 安全公告GHSA-hxf6-58cx-qq3x
修复 Pull RequestTriliumNext/Trilium#8129
CVE 记录 (CVEProject)CVE-2025-68621.json
CWE-208可观察的时序差异
Trilium Notes 仓库TriliumNext/Trilium