
SQLite 3.53.4 - Élevé - Local - Résidu de privilège - FULL JOIN USING ignore sqlite3AuthRead
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-fj-using-auth
Write-up : https://abraxaslabs.tech/research/sqlite-fj-using-auth
Classe : Résidu de privilège Portée : Locale
SQLite 3.53.4 (b09c88c / SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc) - Hwaci
lookupName() réécrit une colonne FULL JOIN USING en coalesce(...) (TK_FUNCTION). sqlite3AuthRead ne s'exécute que pour TK_COLUMN / TK_TRIGGER, donc les colonnes USING ne reçoivent jamais de callback SQLITE_READ. Un embedder qui a installé sqlite3_set_authorizer et qui DENY/IGNORE READ sur t2.x renvoie tout de même cette colonne via SELECT x FROM t1 FULL JOIN t2 USING(x).
L'authorizer est désactivé à l'ouverture par défaut. Résidu de cette API C. Pas de RCE. FULL JOIN ON et LEFT JOIN USING restent refusés / sans fuite. Un coalesce(t2.x) explicite est toujours autorisé.
| ID | pas encore de CVE |
| Classe | Résidu de privilège (contournement de l'authorizer au niveau colonne) |
| Portée | Locale (embedder sqlite3_set_authorizer ; SQL de l'attaquant) |
| CWE | CWE-863, CWE-284 |
| CVSS | Élevé : 7.5 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| Produit | SQLite (miroir GitHub sqlite/sqlite) |
| Affecté | 3.53.4 (b09c88c14082339b66c7b7158d609a771e64ca69). Le correctif authorizer FULL JOIN USING réservé à la 3.54 (2cb2287768) n'est pas présent sur cette GA. |
| Auth | embedder ayant installé sqlite3_set_authorizer ; le callback par défaut est NULL |
| Licence | GNU Affero GPL v3.0 |
| Lab | 127.0.0.1:18840 uniquement. Chaîne témoin. Pas de RCE. |
Face à un embedder qui a installé sqlite3_set_authorizer comme ACL par colonne, préparer SELECT x FROM t1 FULL JOIN t2 USING(x) (ou NATURAL FULL JOIN). Un simple SELECT x FROM t2 est refusé (SQLITE_AUTH 23). La forme FULL JOIN USING renvoie la colonne dont le READ est refusé. Aucun callback READ t2.x ne se déclenche.
L'authorizer est désactivé sauf si l'embedder en installe un. Le sqlite3_open par défaut n'est pas concerné par ce résidu. Pas de RCE.
Vingt recherches dans le code source de la 3.53.4 après PHP. La liste d'exclusion mentionnait déjà le commit de vérification authorizer FULL JOIN USING de la 3.54. Il manque toujours sur la dernière GA. pExpr->op vaut TK_FUNCTION à lookupname_end, donc la barrière AuthRead ne s'exécute jamais. WRC_Prune empêche également le walker de descendre dans les arguments de coalesce.
lookupname_end:
if( cnt==1 ){
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pParse->db->xAuth
&& (pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER)
){
sqlite3AuthRead(pParse, pExpr, pSchema, pNC->pSrcList);
}
#endif
Les faux pas déjà consignés : considérer l'authorizer comme activé par défaut ; s'attendre à ce que LEFT JOIN USING ou FULL JOIN ON provoquent une fuite ; s'attendre à ce que coalesce(t2.x) explicite contourne AuthRead ; épingler la version 3.54.0 alors qu'elle était encore à l'état de brouillon.
cd lab
./run.sh
Compile l'amalgamation officielle sqlite-src-3530400. Le harnais est lab/auth.c. Boucle locale 127.0.0.1:18840. Authorizer DENY READ t2.x. SELECT x FROM t2 refusé. SELECT x FROM t1 FULL JOIN t2 USING(x) renvoie le témoin, 0 READ t2.x. FULL JOIN ON refusé. LEFT JOIN USING sans fuite. La base de référence IGNORE est NULL ; IGNORE FULL JOIN USING fuit toujours.
SUCCESS sqlite-fj-using-auth how=full-join-using-skip-authread baseline=denied fj-using=witness fj-on=denied left-using=no-leak SQLITE-FJ-USING-AUTH-WITNESS
Boucler sqlite3AuthRead sur chaque enfant pFJMatch après la réécriture de coalesce, comme le fait le trunk 2cb2287768 / Git 5694c3bb pour 3.54. Autoriser uniquement a[0] (bbd69ce274) ne suffit pas. LEFT JOIN USING et FULL JOIN ON autorisent déjà ; ils ne constituent pas ce reliquat.
b09c88c14082339b66c7b7158d609a771e64ca69)src/resolve.c réécriture de coalesce de lookupName et porte AuthReadsrc/auth.c sqlite3AuthRead / sqlite3AuthReadCol