
SQLite 3.53.4 - Alta - Local - Privilégio remanescente - FULL JOIN USING ignora 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: Privilégio residual Alcance: Local
SQLite 3.53.4 (b09c88c / SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc) - Hwaci
lookupName() reescreve uma coluna de FULL JOIN USING para coalesce(...) (TK_FUNCTION). sqlite3AuthRead é executado apenas para TK_COLUMN / TK_TRIGGER, portanto colunas USING nunca recebem um callback SQLITE_READ. Um embedder que instalou sqlite3_set_authorizer e aplica DENY/IGNORE em READ sobre t2.x ainda retorna essa coluna por meio de SELECT x FROM t1 FULL JOIN t2 USING(x).
O authorizer fica desativado na abertura padrão. Resíduo dessa API C. Não é RCE. FULL JOIN ON e LEFT JOIN USING continuam negados / sem vazamento. coalesce(t2.x) explícito ainda é autorizado.
| ID | ainda sem CVE |
| Classe | Privilégio residual (omissão do authorizer em nível de coluna) |
| Alcance | Local (embedder sqlite3_set_authorizer; SQL do atacante) |
| CWE | CWE-863, CWE-284 |
| CVSS | Alto: 7.5 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| Produto | SQLite (espelho no GitHub sqlite/sqlite) |
| Afetado | 3.53.4 (b09c88c14082339b66c7b7158d609a771e64ca69). A correção do authorizer para FULL JOIN USING, exclusiva da 3.54 (2cb2287768), não está nesta GA. |
| Auth | embedder instalou sqlite3_set_authorizer; o callback padrão é NULL |
| Licença | GNU Affero GPL v3.0 |
| Lab | apenas 127.0.0.1:18840. String testemunha. Não é RCE. |
Contra um embedder que instalou sqlite3_set_authorizer como ACL de coluna, prepare SELECT x FROM t1 FULL JOIN t2 USING(x) (ou NATURAL FULL JOIN). SELECT x FROM t2 isolado é negado (SQLITE_AUTH 23). A forma FULL JOIN USING retorna a coluna com READ negado. Nenhum callback READ t2.x é disparado.
O authorizer fica desativado a menos que o embedder instale um. O sqlite3_open padrão não apresenta este resíduo. Não é RCE.
Vinte buscas no código-fonte da 3.53.4 depois do PHP. A lista de exclusão já mencionava o check-in do authorizer para FULL JOIN USING da 3.54. Ele ainda está ausente na GA mais recente. pExpr->op é TK_FUNCTION em lookupname_end, então a verificação AuthRead nunca é executada. WRC_Prune também impede que o walker desça nos argumentos do 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
Decisões erradas já registradas: tratar o authorizer como ativado por padrão; esperar que LEFT JOIN USING ou FULL JOIN ON vazassem; esperar que coalesce(t2.x) explícito ignorasse o AuthRead; fixar a versão 3.54.0 enquanto ainda era rascunho.
cd lab
./run.sh
Compila a amalgamação oficial sqlite-src-3530400. O harness é lab/auth.c. Loopback 127.0.0.1:18840. Authorizer DENY READ t2.x. SELECT x FROM t2 negado. SELECT x FROM t1 FULL JOIN t2 USING(x) retorna a testemunha, 0 READ t2.x. FULL JOIN ON negado. LEFT JOIN USING sem vazamento. A linha de base IGNORE é NULL; IGNORE FULL JOIN USING ainda vaza.
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
Faça o loop de sqlite3AuthRead sobre cada filho de pFJMatch após a reescrita de coalesce, da mesma forma que o trunk 2cb2287768 / Git 5694c3bb faz para a 3.54. Autorizar apenas a[0] (bbd69ce274) não é suficiente. LEFT JOIN USING e FULL JOIN ON já autorizam; eles não são este resíduo.
b09c88c14082339b66c7b7158d609a771e64ca69)src/resolve.c reescrita de coalesce em lookupName e gate de AuthReadsrc/auth.c sqlite3AuthRead / sqlite3AuthReadCol