
SQLite 3.53.4 - High - Local - 권한 잔여 - FULL JOIN USING이 sqlite3AuthRead를 건너뜀
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-fj-using-auth
분석 문서: https://abraxaslabs.tech/research/sqlite-fj-using-auth
분류: 권한 잔여 도달 범위: 로컬
SQLite 3.53.4 (b09c88c / SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc) - Hwaci
lookupName()는 FULL JOIN USING 컬럼을 coalesce(...)(TK_FUNCTION)로 재작성합니다. sqlite3AuthRead는 TK_COLUMN / TK_TRIGGER에 대해서만 실행되므로, USING 컬럼은 SQLITE_READ 콜백을 절대 받지 않습니다. sqlite3_set_authorizer를 설치하고 t2.x에 대한 READ를 DENY/IGNORE한 임베더도 SELECT x FROM t1 FULL JOIN t2 USING(x)를 통해 해당 컬럼을 여전히 반환합니다.
Authorizer는 기본 open 시 꺼져 있습니다. 해당 C API의 잔여물입니다. RCE는 아닙니다. FULL JOIN ON과 LEFT JOIN USING은 계속 거부되거나 누출되지 않습니다. 명시적 coalesce(t2.x)는 여전히 권한 검사를 받습니다.
| ID | 아직 CVE 없음 |
| 분류 | 권한 잔여 (컬럼 수준 authorizer 건너뜀) |
| 도달 범위 | 로컬 (임베더 sqlite3_set_authorizer; 공격자 SQL) |
| CWE | CWE-863, CWE-284 |
| CVSS | 높음: 7.5 CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N |
| 제품 | SQLite (GitHub 미러 sqlite/sqlite) |
| 영향 받는 버전 | 3.53.4 (b09c88c14082339b66c7b7158d609a771e64ca69). 3.54 전용 authorizer FULL JOIN USING 수정(2cb2287768)은 이 GA에 포함되지 않았습니다. |
| 인증 | 임베더가 sqlite3_set_authorizer를 설치함; 기본 콜백은 NULL |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1:18840 전용. 증거 문자열. RCE 아님. |
sqlite3_set_authorizer를 컬럼 ACL로 설치한 임베더를 대상으로, SELECT x FROM t1 FULL JOIN t2 USING(x)(또는 NATURAL FULL JOIN)를 준비합니다. 단순한 SELECT x FROM t2는 거부됩니다(SQLITE_AUTH 23). FULL JOIN USING 형태는 READ가 거부된 컬럼을 반환합니다. READ t2.x 콜백은 하나도 발생하지 않습니다.
Authorizer는 임베더가 설치하지 않는 한 꺼져 있습니다. 기본 sqlite3_open은 이 잔여물에 해당하지 않습니다. RCE는 아닙니다.
PHP 이후 3.53.4를 대상으로 스무 차례 소스 헌팅을 진행했습니다. 스킵 목록에는 이미 3.54의 FULL JOIN USING authorizer 체크인이 명시되어 있었습니다. 최신 GA에는 여전히 빠져 있습니다. lookupname_end에서 pExpr->op가 TK_FUNCTION이므로 AuthRead 게이트가 절대 실행되지 않습니다. 또한 WRC_Prune이 워커가 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
잘못된 전환으로 이미 기록된 것들: authorizer를 기본 활성화로 간주한 것; LEFT JOIN USING 또는 FULL JOIN ON이 유출될 것이라 기대한 것; 명시적 coalesce(t2.x)가 AuthRead를 건너뛸 것이라 기대한 것; 3.54.0이 아직 초안이었을 때 고정한 것.
cd lab
./run.sh
공식 sqlite-src-3530400 아말감을 빌드합니다. 하네스는 lab/auth.c입니다. 루프백 127.0.0.1:18840. Authorizer가 t2.x에 대한 READ를 DENY합니다. SELECT x FROM t2는 거부됩니다. SELECT x FROM t1 FULL JOIN t2 USING(x)는 witness를 반환하며, READ t2.x는 0회입니다. FULL JOIN ON은 거부됩니다. LEFT JOIN USING은 누출이 없습니다. IGNORE 기준선은 NULL이며, IGNORE FULL JOIN USING은 여전히 누출됩니다.
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
3.54에서 트렁크 2cb2287768 / Git 5694c3bb가 하는 방식대로, 병합(coalesce) 재작성 이후 모든 pFJMatch 자식에 대해 sqlite3AuthRead를 반복 실행합니다. a[0]만 권한을 부여하는 것(bbd69ce274)으로는 충분하지 않습니다. LEFT JOIN USING과 FULL JOIN ON은 이미 권한을 부여하므로, 이 잔여 문제에 해당하지 않습니다.
b09c88c14082339b66c7b7158d609a771e64ca69)src/resolve.c lookupName 병합 재작성 및 AuthRead 게이트src/auth.c sqlite3AuthRead / sqlite3AuthReadCol