
SQLite 3.53.4 - Alta - Local - Vazamento de informação - Incompatibilidade de tamanho de página WAL/DB na cauda de página não inicializada
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-wal-pagesize
Análise: https://abraxaslabs.tech/research/sqlite-wal-pagesize
Classe: Vazamento de informação Alcance: Local
O SQLite 3.53.4 (b09c88c) ainda faz leitura curta de um frame WAL para uma página completa do pager sem memset da cauda. walIndexRecover aceita qualquer tamanho de página WAL potência de dois em [512, SQLITE_MAX_PAGE_SIZE] e nunca o compara com o tamanho de página do banco de dados. Slots de pcache reciclados então retornam bytes anteriores de heap/página por meio de SQL comum.
Lab: .db em modo WAL com páginas de 4096, cabeçalho do -wal irmão com tamanho de página 512, SELECT b FROM t retornou 2000 bytes. A cauda além do frame de 512 bytes era SQLITE-WAL-PAGESIZE-WITNESS. Não é RCE.
| ID | ainda sem CVE |
| Classe | Vazamento de informação (cauda não inicializada do pager via SQL) |
| Alcance | Local (.db não confiável mais -wal irmão) |
| CWE | CWE-908, CWE-200 |
| CVSS | Alto: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| Produto | SQLite (Hwaci) |
| Afetado | 3.53.4 (b09c88c14082339b66c7b7158d609a771e64ca69); SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc |
| Autenticação | nenhuma (a vítima abre os arquivos do atacante) |
| Licença | GNU Affero GPL v3.0 |
| Lab | somente 127.0.0.1:18830 |
Entregar um .db em modo WAL mais um -wal irmão cujo tamanho de página no cabeçalho seja uma potência de dois válida menor que a do banco de dados. A recuperação o aceita. sqlite3WalReadFrame copia apenas o tamanho do frame WAL para um buffer do pager dimensionado a partir do .db. Uma célula de folha de tabela que declara um payload maior que esse frame é satisfeita a partir da cauda reciclada do pcache. SELECT / substr() / hex() sobre esse blob retorna bytes residuais de pager/heap de páginas anteriores no mesmo processo.
A incompatibilidade inversa (WAL maior que o pager) resulta em SQLITE_CORRUPT no checkpoint. Este resíduo é apenas do caminho de leitura com WAL menor. Não é RCE.
Vinte buscas no código-fonte do 3.53.4 após a matriz de resíduos do trunk posterior. Winter reportou no fórum como 2026-08-17T15:54:41Z. O trunk f9b4ee3695 / branch-3.53 4fde87b2a0 (2026-08-16) é posterior a este GA (2026-07-24). sqlite3WalReadFrame neste pin ainda é (nOut>sz ? sz : nOut) sem memset da cauda.
Caminho errado: uma célula de folha inicial estava malformada e SELECT retornou SQLITE_CORRUPT rc=11. A célula que funciona declara 2000 bytes de payload local através de um frame de 512 bytes em uma página de pager de 4096 bytes.
cd lab
./run.sh
Compila o SQLite 3.53.4 a partir do zip da fonte canônica. Compõe sqlite-wal-pagesize. Publica 127.0.0.1:18830. Pré-carrega o pcache com 48 linhas testemunha de 4000 bytes, depois SELECT b FROM t na folha de leitura curta.
SUCCESS sqlite-wal-pagesize how=wal-shortread-pcache-tail len=2000 rootpage=2 SQLITE-WAL-PAGESIZE-WITNESS
Compare o tamanho da página do cabeçalho do WAL com o tamanho da página do banco de dados durante a recuperação. Quando eles divergirem, recuse o WAL ou inicialize completamente a página do pager:
if( nOut>sz ){
memset(pOut+sz, 0, nOut-sz);
nOut = sz;
}
Esse trecho está no trunk após este GA. Não está na 3.53.4.
b09c88c14082339b66c7b7158d609a771e64ca69)src/wal.c sqlite3WalReadFrame, walIndexRecoversrc/pager.c readDbPage