
SQLite 3.53.4 - Élevé - Local - Fuite d'informations - Incohérence de taille de page WAL/DB sur la fin de page non initialisée
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-wal-pagesize
Write-up : https://abraxaslabs.tech/research/sqlite-wal-pagesize
Classe : Fuite d'informations Portée : Locale
SQLite 3.53.4 (b09c88c) effectue toujours une lecture courte d'une trame WAL dans une page de pager complète sans memset de la queue. walIndexRecover accepte toute taille de page WAL puissance de deux dans [512, SQLITE_MAX_PAGE_SIZE] et ne la compare jamais à la taille de page de la base de données. Les slots pcache recyclés renvoient alors des octets résiduels du tas ou de pages précédentes via du SQL ordinaire.
Labo : .db en mode WAL avec pages de 4096, en-tête -wal frère avec taille de page 512, SELECT b FROM t a renvoyé 2000 octets. La queue au-delà de la trame de 512 octets était SQLITE-WAL-PAGESIZE-WITNESS. Pas de RCE.
| ID | pas encore de CVE |
| Classe | Fuite d'informations (queue de pager non initialisée via SQL) |
| Portée | Locale (.db non fiable plus -wal frère) |
| CWE | CWE-908, CWE-200 |
| CVSS | Élevé : 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N |
| Produit | SQLite (Hwaci) |
| Affecté | 3.53.4 (b09c88c14082339b66c7b7158d609a771e64ca69) ; SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc |
| Auth | aucune (la victime ouvre les fichiers de l'attaquant) |
| Licence | GNU Affero GPL v3.0 |
| Labo | 127.0.0.1:18830 uniquement |
Livrer un .db en mode WAL accompagné d'un -wal frère dont la taille de page d'en-tête est une puissance de deux valide plus petite que celle de la base de données. La récupération l'accepte. sqlite3WalReadFrame ne copie que la taille de la trame WAL dans un tampon de pager dimensionné d'après le .db. Une cellule de feuille de table qui déclare une charge utile plus grande que cette trame est satisfaite depuis la queue recyclée du pcache. SELECT / substr() / hex() sur ce blob renvoie des octets résiduels du pager ou du tas provenant de pages précédentes dans le même processus.
L'incohérence inverse (WAL plus grand que le pager) produit SQLITE_CORRUPT au checkpoint. Ce résidu ne concerne que le chemin de lecture avec WAL plus petit. Pas de RCE.
Vingt recherches dans le code source de 3.53.4 après la matrice de résidus du tronc ultérieur. Winter l'a signalé sur le forum sous 2026-08-17T15:54:41Z. Le tronc f9b4ee3695 / la branche-3.53 4fde87b2a0 (2026-08-16) sont postérieurs à cette GA (2026-07-24). sqlite3WalReadFrame sur ce commit est toujours (nOut>sz ? sz : nOut) sans memset de la queue.
Fausse piste : une première cellule de feuille était malformée et SELECT renvoyait SQLITE_CORRUPT rc=11. La cellule qui fonctionne déclare 2000 octets de charge utile locale sur une trame de 512 octets dans une page de pager de 4096 octets.
cd lab
./run.sh
Compile SQLite 3.53.4 à partir du zip source canonique. Compose sqlite-wal-pagesize. Publié sur 127.0.0.1:18830. Amorçage du pcache avec 48 lignes témoins de 4000 octets, puis SELECT b FROM t sur la feuille à lecture courte.
SUCCESS sqlite-wal-pagesize how=wal-shortread-pcache-tail len=2000 rootpage=2 SQLITE-WAL-PAGESIZE-WITNESS
Comparez la taille de page de l'en-tête WAL à la taille de page de la base de données lors de la récupération. Lorsqu'elles diffèrent, refusez le WAL ou initialisez complètement la page du pager :
if( nOut>sz ){
memset(pOut+sz, 0, nOut-sz);
nOut = sz;
}
Ce hunk se trouve sur le trunk après cette GA. Il n'est pas dans 3.53.4.
b09c88c14082339b66c7b7158d609a771e64ca69)src/wal.c sqlite3WalReadFrame, walIndexRecoversrc/pager.c readDbPage