abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · stirling-storage-folder-idor
Stirling-PDF 3.2.0 - Stirling Tools
类别: IDOR。可达性: 远程 ROLE_USER。
POST /api/v1/processing-folders 除要求用户已登录外,没有任何 @PreAuthorize 限制。即使 policies.allowedFolderRoots 为空,FolderAccessGuard 仍会隐含整个本地存储 basePath(./storage)。LocalStorageProvider 写入路径为 {ownerId}/{uuid}_{filename}。ROLE_USER 可以设置 directory: "storage/<victimUserId>",列出该所有者的 PDF,并通过 replace=true 就地覆盖它们。
直接访问 /api/v1/storage/files/{id} 已被修补(findByIdAndOwner)。在实验环境中,以对等用户身份 GET 受害者的文件会返回 403。遗留问题在于处理文件夹所隐含的根路径,而非存储 CRUD API。
ROLE_USER 可以列出另一用户存储的 PDF 名称并覆盖这些 blob。受害者下载时返回的是被篡改的文件。
| ID | 暂无 CVE |
| CWE | CWE-639 / CWE-73 |
| CVSS | 7.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:N |
| 产品 | Stirling-PDF |
| 受影响版本 | v3.2.0(a7e593728dd9aa81e75318a949789d3c2e9ee754),镜像 stirlingtools/stirling-pdf:3.2.0-fat,login-on,storage.enabled=true |
| 认证 | 默认团队中的 ROLE_USER |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1:18154 |
这是 Stirling-PDF v3.2.0 遗留问题 系列的遗留问题。姊妹项目:stirling-h2-import-leftover(H2 CREATE OR REPLACE ALIAS)。本包是存储 IDOR。
任何已登录的人类 ROLE_USER,在 login-on 的 proprietary/fat 部署且启用本地存储(模板默认)的情况下即可利用。官方 compose 为 login-off 加 DISABLE_ADDITIONAL_FEATURES=true;该部署会对 /api/v1/storage 返回 403,且不包含此控制器。HIT 部署为模板 login-on 加 fat。
权限表(详尽)。与 Signal-Server Dropwizard admin 同等门槛。
| 维度 | 方法 + 路径 | 授予能力 | 来源 |
|---|---|---|---|
| 侦察 | ROLE_USER GET /api/v1/user/users | 获取 admin、对等用户及 STIRLING-PDF-BACKEND-API-USER 的数字 userId | 实验验证 |
| 侦察 | POST /api/v1/processing-folders {directory:"storage/1"} 然后 GET /api/v1/processing-folders/{id}/files | 获取 admin 存储的 PDF 的名称、大小、mtime(5341de35-8729-49cf-92d0-c8284e05bfc5_victim-lab.pdf) | 实验验证 |
| 完整性 | POST /api/v1/processing-folders/{id}/sweep 配合 /api/v1/security/add-watermark,然后受害者 Range GET /api/v1/storage/files/1/download | 就地重写。受害者 206 / 3450 字节包含 STIRLING-STORAGE-FOLDER-IDOR-WITNESS | 实验验证(replace=true) |
| 机密性 | 同样的 sweep 加上攻击者可读取的团队 outputId / 出站步骤 | 受害者 PDF 字节的副本 | 推断。列出/覆盖并不需要 |
在此版本上保持关闭
| 轴 | 方法 + 路径 | 为何被关闭 |
|---|---|---|
| 侦察 | 对非共享文件执行 GET /api/v1/storage/files/{id} | 403 Access denied。已在文件 id 1 上实验验证 |
| 侦察 | 未认证访问 /api/v1/storage/** | 登录关闭时返回 403(ensureStorageEnabled) |
| 完整性 | 跨所有者的文件夹 UUID CRUD | findByIdAndOwner |
| 完整性 | LocalStorageProvider 的 .. / 绝对路径键 | 规范化后 Path.startsWith(basePath) |
| 完整性 | 超轻量镜像 | 专有处理文件夹控制器缺失 |
GET /api/v1/user/users 列出 STIRLING-PDF-BACKEND-API-USER 是额外的 IOC。我没有将其作为独立的遗留问题提交。覆盖后,未使用 Range 的受害者下载会返回 500,因为 FileStorageController 仍然公布原始数据库中的 sizeBytes。使用 Range 则正常。水印文本在 FlateDecode 中为 Identity-H;该 oracle 会解压流。
3.x 增加了本地存储和处理文件夹。存储 CRUD 按所有者限定作用域。FolderAccessGuard.serverStorageRoots 为整棵树返回 Path.of(basePath),而不是 basePath/{currentUserId}。storage/<victimId> 以该隐含根路径为 startsWith 前缀。
实验环境将 peeruser 创建为 ROLE_USER,以管理员身份上传受害者 PDF,证明直接存储 GET 返回 403,将处理文件夹指向 storage/1,列出带 UUID 前缀的名称,扫描水印,然后以受害者身份进行 Range 下载。
走过的弯路:认为直接存储 IDOR 仍然开放(403);将登录关闭的官方 compose 当作 HIT 部署(存储 403,控制器缺失);声称在没有 outputId 的情况下存在攻击者可读的字节副本。
python3 stirling-storage-folder-idor-Abraxas-Labs.py
或
cd lab
./run.sh
仅针对 http://127.0.0.1:18154。镜像 stirlingtools/stirling-pdf:3.2.0-fat。需要 Docker。启用登录。启动器会 chdir 进入 lab/ 并执行 run.sh。
IOC direct-storage-get http=403
IOC processing-folders-save directory=storage/1 http=202
IOC listed-peer ... victim-lab.pdf
IOC victim-download attempt=1 http=206 bytes=3450 witness=1
SUCCESS stirling-storage-folder-idor direct-storage-403=yes listed-peer-pdf=yes download-has-witness=yes STIRLING-STORAGE-FOLDER-IDOR-WITNESS
在多用户服务器上,将磁盘 directory 的隐式存储根目录限定为 basePath/{currentUserId}。像 findByIdAndOwner 已经拒绝外部文件 id 那样,拒绝 storage/<otherId>。在就地重写后重新计算对外公布的 sizeBytes。
针对已修补的构建重新运行 回环客户端:以 peeruser 身份访问 directory=storage/1 必须返回 403,且列出的对等用户必须保持为空。
在此之前,不要将“我修补了 /api/v1/storage/files/{id}”视为“我已将每个接受 ./storage 下磁盘路径的 API 都限定了作用域”。
a7e593728dd9aa81e75318a949789d3c2e9ee754)供应商接收渠道:GitHub Security Advisory 标签页或 [email protected]。我不会在 Stirling-Tools/Stirling-PDF 上公开提交 issue。
Abraxas Labs https://abraxaslabs.tech https://github.com/abraxas [email protected]