
SQLite 3.53.4 - Alto - Locale - Divulgazione di informazioni - Disallineamento della dimensione di pagina WAL/DB e coda di pagina non inizializzata
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-wal-pagesize
Write-up: https://abraxaslabs.tech/research/sqlite-wal-pagesize
Classe: Info leak Portata: Locale
SQLite 3.53.4 (b09c88c) legge ancora un frame WAL in modo incompleto dentro una pagina pager completa senza memset della coda. walIndexRecover accetta qualsiasi dimensione di pagina WAL potenza di due in [512, SQLITE_MAX_PAGE_SIZE] e non la confronta mai con la dimensione di pagina del database. Gli slot pcache riciclati restituiscono quindi byte heap/pagina precedenti tramite SQL ordinario.
Lab: .db in modalità WAL con pagine da 4096, header -wal affiancato con dimensione di pagina 512, SELECT b FROM t ha restituito 2000 byte. La coda oltre il frame da 512 byte era SQLITE-WAL-PAGESIZE-WITNESS. Non è RCE.
| ID | nessuna CVE al momento |
| Classe | Info leak (coda pager non inizializzata tramite SQL) |
| Portata | Locale (.db non attendibile più -wal affiancato) |
| 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 |
| Prodotto | SQLite (Hwaci) |
| Affetto | 3.53.4 (b09c88c14082339b66c7b7158d609a771e64ca69); SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc |
| Auth | nessuna (la vittima apre i file dell'attaccante) |
| Licenza | GNU Affero GPL v3.0 |
| Lab | solo 127.0.0.1:18830 |
Distribuire un .db in modalità WAL più un -wal affiancato la cui dimensione di pagina nell'header è una potenza di due valida più piccola di quella del database. Il recovery la accetta. sqlite3WalReadFrame copia solo la dimensione del frame WAL in un buffer pager dimensionato in base al .db. Una cella foglia di tabella che dichiara un payload più grande di quel frame viene soddisfatta dalla coda pcache riciclata. SELECT / substr() / hex() su quel blob restituisce byte pager/heap residui da pagine precedenti nello stesso processo.
La discrepanza inversa (WAL più grande del pager) produce SQLITE_CORRUPT al checkpoint. Questo residuo riguarda solo il percorso di lettura con WAL più piccolo. Non è RCE.
Venti ricerche nel codice sorgente di 3.53.4 dopo la matrice dei residui del trunk successivo. Winter l'ha segnalato sul forum come 2026-08-17T15:54:41Z. Il trunk f9b4ee3695 / branch-3.53 4fde87b2a0 (2026-08-16) è successivo a questa GA (2026-07-24). sqlite3WalReadFrame su questo pin è ancora (nOut>sz ? sz : nOut) senza alcun memset della coda.
Falsa pista: una cella foglia iniziale era malformata e SELECT restituiva SQLITE_CORRUPT rc=11. La cella che funziona dichiara 2000 byte di payload locale attraverso un frame da 512 byte su una pagina pager da 4096 byte.
cd lab
./run.sh
Compila SQLite 3.53.4 dallo zip sorgente canonico. Compone sqlite-wal-pagesize. Pubblica 127.0.0.1:18830. Precarica la pcache con 48 righe testimone da 4000 byte, poi esegue SELECT b FROM t sulla foglia short-read.
SUCCESS sqlite-wal-pagesize how=wal-shortread-pcache-tail len=2000 rootpage=2 SQLITE-WAL-PAGESIZE-WITNESS
Confrontare la dimensione della pagina di intestazione del WAL con la dimensione della pagina del database durante il recupero. Quando non coincidono, rifiutare il WAL o inizializzare completamente la pagina del pager:
if( nOut>sz ){
memset(pOut+sz, 0, nOut-sz);
nOut = sz;
}
Quel blocco è sul trunk dopo questa GA. Non è nella 3.53.4.
b09c88c14082339b66c7b7158d609a771e64ca69)src/wal.c sqlite3WalReadFrame, walIndexRecoversrc/pager.c readDbPage