## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-V3S9ER-CVE-2026-52886
# 路径遍历:`starts_with()` 前缀检查绕过
**Notepad++ — 通过`session.xml` 的 `backupFilePath` 遍历实现任意文件读取**
## 公告
* **GHSA:** GHSA-rqfm-pw34-r7j6
* **CVE:** CVE-2026-52886
* **严重性:** 中等
* **受影响版本:** < v8.9.6.4
* **已修复版本:** v8.9.7
* **修复提交:** 7e66f36
* **受影响文件:** `PowerEditor/src/Notepad_plus.cpp`(会话恢复 — `backupFilePath` 验证)
* **平台:** Windows 11 Pro x64
* **所需权限:** 标准用户(对 `session.xml` 具有写入权限)
* **研究人员:** v3s9er (RAGE)
* **披露日期:** 2026-06-05
## 摘要
Notepad++ 在会话恢复期间通过 `std::wstring::starts_with()` 对 `backupFilePath` 属性进行原始字符串前缀比较来验证其合法性,**且未先对路径进行规范化处理** 。以合法备份目录前缀开头但包含 `..\` 遍历序列的构造路径能够通过检查,但操作系统打开文件时却会解析到任意位置——从而将任意可读文件的内容加载到编辑器标签页中。
## 技术概述
启用快照(备份)模式启动时,Notepad++ 会从 `session.xml` 恢复之前的会话。每个条目的 `backupFilePath` 预期位于应用程序的备份目录下。完整性检查仅验证存储的路径是否 _以_ 预期的备份目录字符串开头。由于比较发生在原始、未规范化的字符串上,攻击者可以预先附加合法前缀,然后通过 `..\` 序列走出该目录。
## 根本原因
检查针对文本前缀;而使用方打开的是操作系统解析后的路径。一旦存在 `..\`,两者便不一致。
操作| 来源| 行为
---|---|---
检查| 原始 `backupFilePath` 字符串| `starts_with(backupDir)` — 前缀匹配即通过
使用| 操作系统解析后的路径| `..\` 序列被折叠至任意位置
## 攻击场景
**前提条件:** 对 `session.xml` 具有写入权限,已启用快照/备份模式。
**步骤:**
1. 覆盖 `session.xml`,注入构造的 `backupFilePath`: `<backupDir>\..\..\..\..\Users\victim\.ssh\id_rsa`
2. 前缀 `<backupDir>\` 满足 `starts_with()`,因此验证通过。
3. 启动 Notepad++(触发会话恢复)。
4. 操作系统折叠 `..\` 序列;目标文件被打开。
5. 任意文件的内容被加载到编辑器标签页中。
**结果:** 只读外泄 — 目标文件内容在编辑器中可见,包括 SSH 密钥、环境配置文件、凭据存储等敏感文件。
## 影响
* **类型:** 任意文件读取(路径遍历)
* **是否需要管理员权限:** 否
* **UAC 提示:** 否
* **暴露范围:** SSH 私钥、`.env` / 配置文件、凭据存储 — 用户可读取的任何文件
* **CWE:** CWE-22(对受限目录的路径名限制不当)
## 概念验证
**要求:**
* Notepad++ v8.9.6.2 便携版 x64,已配置备份/快照功能
* 对 `session.xml` 具有写入权限
* `backupFilePath` 载荷:备份目录前缀 + `..\` 遍历序列 + 目标文件路径
注入构造的路径并启动应用程序后,目标文件会被加载到编辑器标签页中。
## 补丁分析
该修复(提交 `7e66f36`)在验证之前执行了正确的路径**规范化** ,因此 `..\` 序列会在前缀比较之前被折叠——现在检查的路径与使用的路径保持一致。
## 参考
* GHSA-rqfm-pw34-r7j6
* CVE-2026-52886
* 提交 7e66f36
* Notepad++ v8.9.7 发布版