
細工されたSZ値によって切り詰められた割り当てとzlibの境界外書き込みを引き起こす、SQLite SQLARのヒープバッファオーバーフローに対するアドバイザリとAddressSanitizer再現コード。
CVE-2026-39113は、SQLiteのオプションSQLAR拡張機能におけるヒープバッファオーバーフローです。拡張機能がロードされているアプリケーションでは、制御された圧縮blobとサイズを指定してsqlar_uncompress()を呼び出せる攻撃者により、LP64システム上でzlibがヒープ割り当て領域を超えて書き込む可能性があります。これはホストプロセス内のメモリ安全性の境界違反であり、SQLiteデータベースファイルの解析問題、認証バイパス、またはすべてのデフォルトのSQLiteデプロイメントで到達可能な欠陥ではありません。
脆弱な動作は、2026-03-11にGitコミット169f68e(Fossilチェックイン8bdc0d485e3ad0c7...)によって導入され、2026-04-01にGitコミット34e139d(Fossilチェックイン6194f3b5314ef98b...)によって修正されました。影響範囲は、169f68eから34e139dの親までのソーススナップショットおよびカスタムビルドです。公式のSQLiteリリースで脆弱性が確認されたものはありません:SQLite 3.52.0は導入前であり、SQLite 3.53.0には導入変更と修正の両方が含まれています。したがって、SQLite 3.53.0は修正コードを含む最初の公式リリースであり、影響を受けるリリースではありません。
問題の脆弱なリビジョン、導入および修正の各変更、そして3.52.0と3.53.0のリリーススナップショットをレビューしました。また、使い捨てのWSL2 Ubuntu 24.04環境での許可された実行から保存された出力も調査しました。AddressSanitizerはヒープバッファオーバーフローとそれに続くプロセス終了を観測し、ネイティブヒープ破壊とサービス拒否を立証しました。コード実行は実証されていません。
SQLARはSQLiteのアーカイブ形式です。ext/misc/sqlar.cのオプション拡張機能は、sqlar_compress()とsqlar_uncompress()をSQL関数として登録します。これはSQLiteを使用するすべてのアプリケーションに含まれるわけではなく、脆弱な経路に到達するには拡張機能が存在しロードされている必要があります。
このレポートでは、Malloryはsqlar_uncompress()に供給されるblobとSZ引数を制御します:
SELECT sqlar_uncompress(?1, ?2);
テスト環境は、32ビットのint、64ビットのsqlite3_int64およびzlibのuLongfを備えていました。この関数は、zlibが書き込みを許可される量と少なくとも同じ量のメモリを割り当てる必要があります。しかし、脆弱なソースは、uncompress()には完全な値を使用しながら、sqlite3_malloc()の32ビットのパラメータ型に64ビットのサイズを変換します。
脆弱なソーススナップショットは、構成中にConfiguring SQLite version 3.53.0と出力しました。この開発版のバージョン文字列を、そのソースに修正が含まれる2026-04-09付の公式SQLite 3.53.0リリースと混同してはなりません。
評価したリビジョンでは、ext/misc/sqlar.cのsqlarUncompressFunc()は、攻撃者が制御するサイズを64ビット整数として読み取ります:
sqlite3_int64 sz;
sz = sqlite3_value_int64(argv[1]);
szが正で、入力blobの長さと異なる場合、同じ値が互換性のない2つの方法で使用されます:
uLongf szf = sz;
const Bytef *pData = sqlite3_value_blob(argv[0]);
Bytef *pOut = sqlite3_malloc(sz);
if( pOut==0 ){
sqlite3_result_error_nomem(context);
}else if( Z_OK!=uncompress(pOut, &szf, pData, nData) ){
sqlite3_result_error(context, "error in uncompress()", -1);
}
このリビジョンでは、SQLiteはsqlite3_malloc(int)を宣言しています。テストしたLP64ビルドでは、PoC値4294967328(0x100000020)はそのAPIに渡されたときに32になりましたが、szfは完全な64ビット値を保持していました。そのためSQLiteは小さな割り当てを行いましたが、zlibには出力バッファが4GiB以上を保持できると通知されました。4096バイトのデータを表す42バイトのblobを解凍すると、割り当て境界を越えました。
この不一致は、2026-03-11の変更が、割り当てAPIを変更せずにsqlite3_value_int()をsqlite3_value_int64()に置き換えたときにプロジェクトに導入されました。SQLite 3.52.0のソースレビューでは、以前の32ビット読み取りが示されており、したがって全幅/短い割り当ての不一致はそこには存在しませんでした。2026-04-01の修正は、割り当てをsqlite3_malloc64(sz)に変更しました。公式3.53.0タグのソースレビューにより、その修正された呼び出しが確認されています。
実証されたプリミティブは、SQLiteをホストするプロセスにおけるヒープ領域外書き込みです。保存された実行では、AddressSanitizerがsqlite3_malloc()を介して割り当てられた40バイトのヒープ領域の直後にある最初の不正な1バイト書き込みを検出し、その後にアボートが発生しました。これはプロセスクラッシュとサービス拒否を直接的に裏付けます。
悪用には、以下のすべてが必要です:
SZ値を指定してsqlar_uncompress()を呼び出せること;intが32ビットであり、sqlite3_int64とzlibのuLongfが64ビットであること;およびPoCは解凍されたバイトを制御します。これはネイティブヒープ破壊の深刻度に関連します。ただし、このプリミティブをコード実行に変えるには、アロケータのレイアウト、周囲のプロセス状態、緩和策、および適切なアプリケーションレベルの経路に依存します。そのようなチェーンはテストも実証もされていないため、このレポートはコード実行を主張するものではありません。
保存された実行には、修正されたリビジョンに対する実行時のネガティブコントロールは含まれていませんでした。2つのソースレベルのチェックが説明を絞り込みます:SQLite 3.52.0は32ビットAPIでサイズを読み取り、公式3.53.0ソースはsqlite3_malloc64()で割り当てます。これらのチェックは特定された導入と修正を裏付けますが、実行された修正対象テストとして提示されているわけではありません。このオプション拡張機能をロードするアプリケーションの普及率は不明です。
リポジトリには以下が含まれます:
poc/verify_sqlar_poc.c:4096バイトのペイロードを作成し、圧縮し、sqlar.soをロードして、SZ = 4294967328をバインドします;poc/reproduce.sh:固定されたSQLiteとzlibのリビジョンをクローンし、AddressSanitizer付きでビルドし、拡張機能とハーネスをコンパイルして、トリガーを実行します;およびevidence/asan-summary.txt:観測された許可された実行のパス正規化された要約。再現スクリプトは、使い捨てのLinuxまたはWSL環境でのみ実行してください。これは意図的にメモリ破壊とAddressSanitizerのアボートを引き起こします。スクリプトにはgit、make、Cコンパイラ、標準的なビルドツール、およびネットワークアクセスが必要です:
chmod +x poc/reproduce.sh
./poc/reproduce.sh
再現スクリプトは2026-08-21にWSL2上のUbuntu 24.04で再度実行され、同じAddressSanitizerの検出結果を生成しました。その関連出力は次のとおりです:
env: sizeof(int)=4 sizeof(sqlite3_int64)=8 sizeof(uLongf)=8
payload: plain=4096 compressed=42 evil_sz=4294967328 low32=32
ERROR: AddressSanitizer: heap-buffer-overflow
WRITE of size 1
#0 inflate_fast zlib/inffast.c:252
#4 uncompress zlib/uncompr.c:100
#5 sqlarUncompressFunc sqlite/ext/misc/sqlar.c:97
The write occurred immediately after a 40-byte heap region.
SUMMARY: AddressSanitizer: heap-buffer-overflow in inflate_fast
ABORTING
PoC exit status: 1
この出力は、互換性のない型幅と細工されたサイズ、zlibの書き込み、sqlarUncompressFunc()からの呼び出し、および割り当て境界違反を示しています。再現スクリプトは、KEEP_BUILD=1が設定されていない限り、終了時に一時ビルドディレクトリを削除します。
上流はコミット34e139dで脆弱な割り当てを修正しました:
- Bytef *pOut = sqlite3_malloc(sz);
+ Bytef *pOut = sqlite3_malloc64(sz);
これにより、割り当て幅は、uLongf szfに保持されてzlibに渡される正の64ビットのsz値と一致したままになります。修正されたコードは公式SQLite 3.53.0に含まれています。脆弱な範囲を含むソーススナップショットまたはカスタムビルドを使用しているユーザーは、34e139d以降に更新する必要があります。SQLARを必要としないアプリケーションは拡張機能をロードしないようにし、使用するアプリケーションは信頼できない呼び出し元がsqlar_uncompress()に任意の引数を提供できないようにする必要があります。
焦点を絞った回帰テストでは、有効な圧縮blobと、下位32ビットが小さいINT_MAXを超えるSZ値を使用してSQL関数を実行する必要があります。修正されたビルドが切り詰められた割り当てを行わないことを検証し、通常の成功する解凍と無効な入力のエラーケースをコントロールとして保持する必要があります。
CVE-2026-39113は、オプションのSQLAR拡張機能がロードされ、攻撃者が制御する呼び出しがLP64ビルドのsqlar_uncompress()に到達する場合に、169f68eから34e139dの親までのSQLiteソーススナップショットとカスタムビルドにのみ影響します。64ビットのサイズがsqlite3_malloc(int)によって縮小される一方で、zlibは完全な値を保持し、AddressSanitizerで確認されたヒープバッファオーバーフローとプロセスのアボートを引き起こしました。公式のSQLiteリリースで脆弱性が確認されたものはなく、コード実行も実証されていません。sqlite3_malloc64(sz)への上流の変更は公式SQLite 3.53.0に含まれており、割り当て幅の不一致を解消します。