
SQLite 3.53.4 - High - Local - 권한 잔여 - FULL JOIN USING이 sqlite3AuthRead를 건너뜀
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · 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 | High: 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 전용. Witness 문자열. RCE 아님. |
컬럼 ACL로 sqlite3_set_authorizer를 설치한 임베더를 대상으로, 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
coalesce 재작성 후 모든 pFJMatch 자식에 대해 sqlite3AuthRead를 루프로 돌린다. 트렁크 2cb2287768 / Git 5694c3bb가 3.54에서 하는 방식과 같다. a[0]만 인가하는 것(bbd69ce274)은 충분하지 않다. LEFT JOIN USING과 FULL JOIN ON은 이미 인가된다; 그것들은 이 잔여물이 아니다.
b09c88c14082339b66c7b7158d609a771e64ca69)src/resolve.c lookupName coalesce 재작성 및 AuthRead 게이트src/auth.c sqlite3AuthRead / sqlite3AuthReadCol