
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · sqlite-values-union
解説記事: https://abraxaslabs.tech/research/sqlite-values-union
分類: クラッシュ 到達範囲: ローカル
SQLite 3.53.4 (b09c88c) - Hwaci
デフォルトの VALUES はコルーチンを使用する。WITH(またはスキーマのリロード、あるいは非定数の行)を付けると、sqlite3MultiValues が UNION ALL に強制される。SF_Values が設定されている場合、複合 SELECT の長さチェックはスキップされる(parse.y:562-567)。その結果、十分に大きな行リストは SQLITE_LIMIT_EXPR_DEPTH によって拒否され、エラー処理経路で再帰的な sqlite3ExprDeleteNN が C スタックを破壊する。
5000 行の単純な VALUES は問題ない。WITH と 1000 行の組み合わせはクリーンにエラーとなる(Expression tree is too large)。WITH と 300000 行の組み合わせでは、sqlite3ExprDeleteNN 内で ASan のスタックオーバーフローが発生する(rc=134)。RCE ではない。
| ID | CVE 未割り当て |
| 分類 | クラッシュ(ExprDelete での ASan スタックオーバーフロー。RCE は実証されていない) |
| 到達範囲 | ローカル(信頼できない SQL、または VIEW/TRIGGER 内の VALUES) |
| CWE | CWE-674 |
| CVSS | High: 7.5 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H |
| 製品 | SQLite |
| 影響を受けるバージョン | 3.53.4(b09c88c14082339b66c7b7158d609a771e64ca69、SOURCE_ID 2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bcc)。後期トランクの VALUES 複合上限の残骸。 |
| 認証 | 攻撃者の SQL、または UNION ALL フォールバックを引き起こす仕込まれたスキーマ |
| ライセンス | GNU Affero GPL v3.0 |
| ラボ | 127.0.0.1:18820 のみ。ASan アマルガメーション。クラッシュの実証。 |
ホストが prepare する信頼できない SQL を入力として与える。巨大な VALUES リストの先頭に WITH を付けてコルーチン経路を無効化する。パースは式の深さエラーで失敗するはずである。しかし、そのツリーのクリーンアップが sqlite3ExprDeleteNN 内で再帰し、プロセスが死ぬまで続く。
同じフォールバックは、VALUES が VIEW または TRIGGER 内にある場合(db->init.busy)にも発生する。ホストとはエンベッダのことである。CLI、攻撃者の SQL を prepare するアプリ、あるいは悪意ある .db を開くサービスなどが該当する。SQLite は VALUES のバイト列をコードとして評価しない。このクラッシュ自体が本件の発見である。
github.com/sqlite/sqlite のタグ version-3.53.4 を対象に、20 回のソース調査を行った。スキップリストにより、CVE-2026-11824、session NPD、concat_ws、LOOKASIDE、JSON UAF、WAL-reset はすでに除外済みであった。デフォルトの load_extension は無効である。パーサ/VDBE の残骸として残っていたのが、この VALUES UNION ALL のスキップと再帰的デストラクタであった。
if( (p->selFlags & (SF_MultiValue|SF_Values))==0
&& (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0
&& cnt>mxSelect
){
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
}
if( pParse->bHasWith
|| pParse->db->init.busy
|| exprListIsConstant(pParse,pRow)==0
...
){
/* The co-routine method cannot be used. Fall back to UNION ALL. */
...
pSelect->op = TK_ALL;
pSelect->pPrior = pLeft;
}
clearSelect() は pPrior を反復的にたどります。sqlite3ExprDeleteNN() は依然として pRight 上で、また EP_Static が設定されている場合は pLeft 上でも再帰します。
誤った方向性: 1000 行の WITH は文書化された深さ上限でクリーンにエラーとなりクラッシュしません。デストラクタの深さが 8 MiB の C スタックを破壊するには 300000 行が必要でした。単純な VALUES はコルーチン上に留まり、ネガティブコントロールとなります。
cd lab
./run.sh
正規の 3.53.4 ソース zip、ASan sqlite3。sqlite-values-union を構成する。127.0.0.1:18820 を公開する。ループバックにバインドする。
SUCCESS sqlite-values-union how=with-values-union-all-fallback-exprdelete rows=300000 crash=asan-stack-overflow plain=5000 depth-error=1000 SQLITE-VALUES-UNION-WITNESS
他の複合クエリが制限されるのと同じ方法で、SQLITE_LIMIT_COMPOUND_SELECT を VALUES に適用します。削除時に UNION ALL チェーンを反復的に走査するか、ツリーが構築される前に EXPR_DEPTH を制限して、クリーンアップが C スタックから再帰的に外れないようにします。後のトランク(Bug 2026-10-04T05:34:47Z)はこの GA より後です。
b09c88c14082339b66c7b7158d609a771e64ca69)2026-07-24 19:02:57 bf7c7f30031888f4e796e429ab3978879485813aaca6f641c7b33e4e09459bccsrc/parse.y:562-567 SF_Values が設定されている場合の複合 SELECT のスキップsrc/insert.c:681-704 sqlite3MultiValues の UNION ALL フォールバックsrc/expr.c:1406-1430 再帰的な sqlite3ExprDeleteNN