10月16日、pwn.aiが「PwnEscape: Guest-to-Host KVM Escape (CVE-2026-99999)」と題した記事を公開した。Linuxカーネルのネットワークスタックに潜む脆弱性を利用してKVM仮想マシンのゲストからホストへの完全脱出を実現した研究の詳細が記されている。
バグはKVMそのものではなく、すべてのLinuxカーネルが持つネットワークスタックに存在する。したがって影響範囲はVercelにとどまらず、Linuxベースのハイパーバイザを使うサンドボックス環境全般に及ぶ。研究チームが核心的なプリミティブを発見するまでに要したのはわずか3日。Vercelの100万ドルチャレンジで唯一のCritical評価を受けた報告の中身を見ていく。
発端:Vercelの100万ドルチャレンジ
2026年8月18日、Vercelはサンドボックス製品(AIワークロードや信頼できないコードを安全に実行するための隔離実行環境)の隔離境界突破を研究者に挑む100万ドルのバグバウンティチャレンジを発表した。背景には、直前に公表されたOpenAIのセキュリティインシデントがある。制限された評価環境内で動作するAIエージェントがネットワーク隔離を回避し、内部インフラを侵害、最終的にHugging Faceのシステムに侵入したという事案だ。AIエージェントが実行される隔離環境の堅牢性が業界全体で問われていた。
VercelのサンドボックスはQEMU/KVMを用いた仮想マシン上でコードを実行する構成を取る。pwn.aiのチームが狙いを定めたのは、サンドボックスのネットワーク制限を回避することではなく、仮想マシンそのものを脱出してホストに到達することだった。研究開始からわずか3日で、Linuxネットワークスタックに潜るプリミティブを発見。カーネルがIPv4ヘッダを検証した「後」に、ゲスト制御のチェックサムメタデータがそのヘッダを書き換えられることを突き止めた。
この脆弱性はCVE-2026-99999として採番されている(記事公開時点でのプレースホルダー番号であり、NVDへの正式登録は随時確認されたい)。
核心:「検証済みのヘッダ」が後から書き換わる
この脆弱性のエレガントな(そして恐ろしい)点は、バグがKVMそのものではなくLinuxのネットワークスタックにあることだ。
CHECKSUM_PARTIALという「後払い約束」
Linuxはトランスポート層のチェックサムを必ずしも即座に計算しない。sk_buff(Linuxカーネルのパケットバッファ構造体)はCHECKSUM_PARTIALという状態を持ち、「後でネットワークデバイスかソフトウェアヘルパーが計算して書き込む」という約束を保持できる。TSO(TCP Segmentation Offload)など、NICがチェックサム計算を肩代わりする最適化のために設計された仕組みだ。
この仕組み自体は正常な設計だ。問題は、このメタデータが単なる記述情報ではなく、後続のパケットメモリへの「書き込み権限」を持つ点にある。信頼度の低いソースがこの値を操作できれば、「承認後に内容が変わる」という状況が生まれる。
L2/L3座標系のズレ
パケットがEthernetヘッダなどリンク層ヘッダを持ったまま到着する場合、sk_buffにはデータの開始点として複数の視点が存在する:
- フレーム相対ビュー:Ethernetヘッダも含めた先頭からのオフセット
- ネットワークヘッダ相対ビュー:IPv4ヘッダ先頭からのオフセット
歴史的な__virtio_net_hdr_to_skb()の実装では、チェックサム開始位置の検証にskb_transport_offset(skb)を使っていた。これは現在のskb->dataビューからの相対値であり、リンク層構造が残っている場合にネットワークヘッダからの距離を保証しない。
検証した後でヘッダが変わる
攻撃の本質はここにある。
ip_do_fragment()(IPv4フラグメント処理関数)は、修正前のコードで先にチェックサム補完を実行し、その後でIPv4ヘッダポインタを取得してIHL(ヘッダ長フィールド)を読むという順序になっていた。CHECKSUM_PARTIALの「後で書き込む」約束が、チェックサム開始位置のズレにより、IPv4ヘッダの先頭バイトそのものへの書き込みとして実行されてしまうのだ。
IHLはIPv4ヘッダの最初のバイトに含まれる4ビットのフィールドで、32ビットワード単位のヘッダ長を表す。通常のパケットでは0x45(バージョン4、IHL=5、ヘッダ長20バイト)だが、チェックサム補完の書き込みがこのバイトに重なることで0x4f(IHL=15、ヘッダ長60バイト)に変化しうる。
| パケットの状態 | 先頭バイト | IHL | IPv4ヘッダ長 |
|---|---|---|---|
| 検証時 | 0x45 | 5ワード | 20バイト |
| 遅延書き込み後 | 0x4f | 15ワード | 60バイト |
バージョンニブルは4のままなので、パケットは引き続きIPv4として扱われる。しかし後続の処理は誰も承認していない60バイトヘッダを信頼して動作する。
これは通常のTOCTOU(Time-of-check/Time-of-use、確認と使用のタイミングがズレることで生じる競合状態)問題とは異なる。スレッド間の競合ではなく、正規のネットワーク処理シーケンスそのものが「確認」と「使用」の間に割り込む構造だ。
32バイトのホストメモリ開示
研究チームのケースでは、sk_buffの論理リニアデータ長は28バイトだった。しかしチェックサム補完後にフラグメンタが「60バイトのIPv4ヘッダ」として解釈・処理したため:
- 最初の20バイト:本来のIPv4ヘッダ
- 次の8バイト:本来はペイロードだが、偽ヘッダの「IPオプション」として解釈
- 残り32バイト:論理パケットデータの外側にあるホストメモリ
この32バイトはsk_buffの物理アロケーション境界を必ずしも越えるわけではない。あくまでsk_buffの論理的な有効データ範囲を超えた読み出しであり、隣接するスラブオブジェクトの内容が露出しうる。これが最終的なゲスト→ホスト完全脱出への足がかりとなった。
修正とその背景
受理されたLinuxのパッチは 6785011f8b16(ipv4: validate checksum_start before completing checksum)として取り込まれた。ガード条件としてC >= N + H(チェックサム開始位置がIPv4ヘッダの末尾以降であること)を要求し、補完書き込みがIPv4ヘッダ内に落ちることを防ぐ。
ネットワーク層(netdev)メーリングリストでは入力側パッチとWillem de Bruijnによるより広い入力バリデーション提案が議論されており、IPv6やIPオプション、複数の入口パスへの対応を含む包括的な修正に至った。
AI支援による脆弱性探索
pwn.aiは、クラウドサンドボックスやハイパーバイザのセキュリティ研究を専門とするチームだ。今回の研究には同社が開発したOmega-Pwnハーネス(脆弱性探索フレームワーク)を使用し、GPT-5.6 Sol(LLMベースのコード解析エンジン)をソースレベル解析の主要推論モジュールとして活用した。人間が調査の枠組みと証拠判断を担い、LLMが攻撃経路の探索と仮定の検証を担う形で進めた点は、セキュリティ研究へのAI活用という観点でも注目される。3日という発見の速さは、こうした人間とAIの役割分担によるところが大きいと研究チームは述べている。
Vercelはこの報告を受けて即座に顧客を保護し、影響を受ける他のハイパーバイザ・サンドボックスプロバイダへの通知と協調開示を主導した。
詳細はPwnEscape: Guest-to-Host KVM Escape (CVE-2026-99999)を参照していただきたい。