abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-wal-pagesize
类别: 信息泄露 影响范围: 本地
SQLite 3.53.4(b09c88c)在将 WAL 帧短读入完整 pager 页时,仍未对尾部执行 memset。walIndexRecover 接受 [512, SQLITE_MAX_PAGE_SIZE] 范围内任意 2 的幂次方 WAL 页大小,且从不将其与数据库页大小进行比较。随后被回收的 pcache 槽位会通过普通 SQL 返回先前的堆/页字节。
实验环境:4096 页的 WAL 模式 .db,同级 -wal 头部页大小为 512,SELECT b FROM t 返回了 2000 字节。超出 512 字节帧的尾部内容为 SQLITE-WAL-PAGESIZE-WITNESS。并非 RCE。
| ID | 暂无 CVE |
| 类别 | 信息泄露(通过 SQL 泄露未初始化的 pager 尾部) |
| 影响范围 | 本地(不可信的 .db 加上同级 -wal) |
| CWE | CWE-908、CWE-200 |
| CVSS | 高危:7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| 产品 | SQLite(Hwaci) |
| 受影响版本 | 3.53.4(b09c88c14082339b66c7b7158d609a771e64ca69);SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc |
| 认证 | 无(受害者打开攻击者提供的文件) |
| 许可证 | GNU Affero GPL v3.0 |
| 实验环境 | 仅 127.0.0.1:18830 |
提供一个 WAL 模式的 .db 以及一个同级 -wal,其头部页大小是比数据库更小的有效 2 的幂次方。恢复过程会接受它。sqlite3WalReadFrame 仅将 WAL 帧大小复制到按 .db 大小分配的 pager 缓冲区中。一个声称负载大于该帧的表叶子单元会从被回收的 pcache 尾部得到满足。对该 blob 执行 SELECT / substr() / hex() 会返回同一进程中先前页残留的 pager/堆字节。
反向不匹配(WAL 大于 pager)会在检查点时产生 SQLITE_CORRUPT。此残留仅存在于较小 WAL 的读取路径中。并非 RCE。
在后续主干残留矩阵之后,对 3.53.4 进行了二十次源码搜寻。Winter 在论坛上将其报告为 2026-08-17T15:54:41Z。主干 f9b4ee3695 / branch-3.53 4fde87b2a0(2026-08-16)晚于本次 GA(2026-07-24)。在此固定版本上,sqlite3WalReadFrame 仍然是 (nOut>sz ? sz : nOut),且未对尾部执行 memset。
弯路:早期的一个叶子单元格式错误,SELECT 返回了 SQLITE_CORRUPT rc=11。可用的那个单元在 4096 字节的 pager 页上,跨 512 字节帧声称了 2000 字节的本地负载。
cd lab
./run.sh
从官方源码 zip 构建 SQLite 3.53.4。Compose sqlite-wal-pagesize。发布到 127.0.0.1:18830。用 48 个 4000 字节的见证行预热 pcache,然后对短读叶子执行 SELECT b FROM t。
SUCCESS sqlite-wal-pagesize how=wal-shortread-pcache-tail len=2000 rootpage=2 SQLITE-WAL-PAGESIZE-WITNESS
在恢复期间比较 WAL 头部页大小与数据库页大小。当二者不一致时,拒绝该 WAL 或完全初始化 pager 页:
if( nOut>sz ){
memset(pOut+sz, 0, nOut-sz);
nOut = sz;
}
该补丁块位于本次 GA 之后的主干上。它不在 3.53.4 中。
b09c88c14082339b66c7b7158d609a771e64ca69)src/wal.c sqlite3WalReadFrame、walIndexRecoversrc/pager.c readDbPage