Leanはこのプログラムが正しいことを証明したが、その後バグを見つけた
概要
- Leanによる形式検証済みプログラムでバグが発見された事例
- AIエージェントやファジングによる脆弱性発見の進化と現状
- 形式検証の限界と、検証範囲外のバグ発見の実例
- LeanランタイムのバッファオーバーフローやDoS脆弱性の詳細
- 形式検証の有効性と課題についての考察
Leanによる検証済みzlib実装にファジングを適用した事例
- **Leanで形式検証されたzlib実装(lean-zip)**を対象にAIエージェント(Claude)とファジングツール(AFL++、AddressSanitizer、Valgrind、UBSan)を適用
- 105,823,818回のファジング実行により、アプリケーションコード自体にはメモリ脆弱性がゼロであることを確認
- しかし、Leanランタイム(lean_alloc_sarray)にバッファオーバーフローを発見
- lean-zipのアーカイブパーサー部分にDoS脆弱性(大容量メモリ割当によるOOM)も発見
- 検証対象外の部分にバグが集中し、検証範囲内は非常に堅牢であったことを実証
ファジング実験のセットアップと手法
- lean-zipコードベースから定理や仕様・C FFIバインディング・ドキュメントを除去し、純粋に検証済み部分のみを対象
- CLI経由でファジング対象を操作し、AIエージェントがバイアスなくコードを解析
- **6つの攻撃面(ZIP抽出、gzip展開、DEFLATE展開、tar抽出、tar.gz、圧縮)**を用意
- AddressSanitizer、UBSan、Valgrind、cppcheck、flawfinderによる多角的な静的・動的解析
- 既知のzlib CVEパターンを模した48種の手書きエクスプロイトファイルも投入
発見されたバグの詳細
-
バグ1:Leanランタイムのバッファオーバーフロー
- lean_alloc_sarray関数で容量計算時のオーバーフローが発生
- **SIZE_MAX(2の64乗-1)**を指定すると小さいバッファが割り当てられ、nバイト読み込みでオーバーフロー
- 全Lean 4バージョンに影響、再現コード5行で容易に発生
- PRにて修正予定
-
バグ2:lean-zipのアーカイブパーサーにおけるDoS
- ZIPヘッダのcompressedSizeフィールドを検証せずにメモリ割当
- 巨大な値を指定するとプロセスがOOMでパニック
- 他のunzip実装では適切な検証があるが、lean-zipでは未検証
- この部分は形式検証の対象外
形式検証の限界と有効性
- DoS脆弱性は検証未実施領域(アーカイブパーサー)で発生
- lean-zipの証明範囲は圧縮・展開処理のみ
- ヘッダ解析やファイル抽出処理は未検証
- ランタイムのバッファオーバーフローは信頼基盤の問題
- Leanの全証明はランタイムの正しさに依存
- ランタイムのバグは全Leanアプリに波及
- 形式検証が適用された範囲ではC/C++実装に比べて極めて高い堅牢性
- ヒープ・スタックバッファオーバーフロー、use-after-free、未定義動作ゼロ
- CVEクラスの脆弱性が構造的に発生しない
まとめと考察
- 形式検証は適用した範囲で圧倒的な堅牢性を実現
- 検証範囲外や信頼基盤(ランタイム)のバグは防げない
- 検証の強さは「どこまで・何を」問うかと「信頼する基盤」に依存
- AIやファジングの進化により、従来のソフトウェアは脆弱性発見コストが劇的に低下
- 今後のソフトウェア開発には形式検証の適用範囲拡大と、信頼基盤の再検証が必須
形式検証時代の課題と展望
- 形式検証済みコードの安全性は高いが、全体の安全性は信頼基盤・検証範囲次第
- trusted computing base(TCB)の最小化と検証拡大が重要課題
- AIや自動化ツールによる脆弱性発見能力の向上
- 「Quis custodiet ipsos custodes?(誰が監視者を監視するのか)」という根本的問い
- 今後は形式検証+AIファジングの組み合わせが主流となる可能性
- 形式検証の証明範囲・信頼基盤の明確化と継続的な再検証が求められる時代