VirtualBoxのヒープ脆弱性が、未だくすぶり続けている。
2017年のドラフト文書が、VirtualBoxのNATネットワーキングスタックにおけるCVE-2017-3558という欠陥を明らかにした。これは、ゲストVMがホストのユーザースペースへと侵入することを許すものだ。8年が経過した今でも、そのコードパスは不気味なほど似通っており、今日のコンテナ全盛の時代において、再調査に値するほど変更されていない。
VirtualBoxのSlirpヒープは、なぜ隔離を裏切るのか
Slirpは、QEMUとVirtualBoxの両方でNATを支える、古き良きユーザモードネットワーキングエミュレーターだ。ゲストの仮想NICから生のIPパケットを吸い上げ、再パッケージ化し、ホストのソケット経由で送信する――カーネル権限は不要だ。賢いだろう?だが、VirtualBoxはこれを大幅に改変している。ポートを剥ぎ取り、カスタムアロケーターを無理やり組み込んでいるのだ。
各NATインターフェースは、独自のゾーンアロケーターを備える。3,072個のチャンク、各2,048バイト。nmbclusters=1024+32*64だ。フリーリストは上から始まり、下へと進んでいく。インラインメタデータが各チャンクの前に置かれている。
struct item {
uint32_t magic; // (常に0xdead0001)
uma_zone_t zone; // (ゾーンへのポインタ; uma_zone_tはstruct uma_zone *)
uint32_t ref_count;
struct {
struct type *le_next; // (次の要素)
struct type **le_prev; // (次のle_nextのアドレス)
} list; // (フリーリストまたはused_items内のエントリ、使用済みヒープチャンクのリスト)
};
解放処理は連鎖する。m_freem → m_free → mb_free_ext → uma_zfree → uma_zfree_arg → slirp_uma_free。
ここに亀裂がある。uma_zfree_arg()は、プレフィックスを覗き見する。
void uma_zfree_arg(uma_zone_t zone, void *mem, void *flags) {
struct item *it;
[...]
it = &((struct item *)mem)[-1];
Assert((it->magic == ITEM_MAGIC));
Assert((zone->magic == ZONE_MAGIC && zone == it->zone));
zone->pfFree(mem, 0, 0); // (zone->pfFreeはslirp_uma_free)
[...]
}
Assert()はリリースビルドでは削除される――VirtualBoxのダウンロードページにあるようなものだ。マジックチェックも、ゾーン検証もない。
そしてslirp_uma_free()は、it->zoneを無条件に信頼し、pfFiniを引き抜き、以下を呼び出す。
{制御可能なポインタ}({制御可能なポインタ}, {パケットデータへのポインタ}, {制御可能なu32});
任意コード実行。ゲストから制御されたヒープからだ。
2025年でも攻撃者はこれを悪用できるか?
コードの停滞が致命的だ。この投稿はこう指摘する。「記述されたコードの多くは、当時からあまり変わっていないようだ」。VirtualBox 7.0のソースをスポットチェックすると――slirp_uma_freeの骨格はそのまま残っている。リリースビルドでのAssert()除去?健在だ。Linuxホストでは、非リロケータブルバイナリが状況を悪化させる。必要であれば、memcpy()パターンがROP(Return-Oriented Programming)を助けるだろう。
ゲストが細工したイーサネットフレームを送信する――ヒープをオーバーフローさせ、チャンクのitem構造を破壊する。it->zoneを攻撃者のデータに向ける。pfFiniを書き込み可能なガジェットへ。ホストのユーザースペースは乗っ取られる。カーネルへのジャンプは未完の部分だった。VBoxDrv経由の権限昇格を考えてみよう。
リスクは?共有ホスティングVM、ペネトレーションテスト、レッドチームラボでは高い。NATの魅力――ゲストのファイアウォール――が裏目に出る。
Heartbleedのアロケーターの罪と並行している。ベンダーは症状をパッチするが、根本的な腐敗は無視する。VirtualBoxのPR?この復活について沈黙しており、2017年以降のアドバイザリーはない。
ユーザースペースエスケープはカーネルRCEではないが、それは楔だ。そこから、Linuxホストの脆弱性はいくらでもある――Dirty COWの残響を覚えているか?
予測:国家レベルの攻撃者は、エアギャップ運用のためこれを掘り起こすだろう。カーネルのゼロデイに手間をかける必要はない。ユーザースペースへのピボットの方が速いからだ。
なぜVMネットワーキングは地雷原であり続けるのか
NATモードは、ゲストトラフィックをホストのものとして偽装する。セキュリティよりも利便性だ。Slirpのユーザランドでの魅力は、ヒープスプレーの下で崩壊する。
代替手段は?ブリッジドネットワーキングはゲストをむき出しにする――ファイアウォールは必須だ。あるいは、ホストのeBPFでポリシーを管理する。しかし、慣性が支配する。何百万ものユーザーが毎日VBox NATを起動している。
Oracleの管理体制は批判を浴びている。無料、多機能だが、パッチは遅い。この2017年の亡霊はそれを証明している。VMハイパーバイザーは要塞ではない。
今すぐ緩和策を講じよう。可能な限りNATを無効にする。コンパイルする場合は厳密なビルドを実行する。ゲストを監査する――マルウェアはパケットフラッドを愛する。
VMからホストユーザースペースへの、パッチされていない道。恐ろしくも単純だ。
🧬 関連インサイト
よくある質問
VirtualBoxのCVE-2017-3558とは何か? NATモードにおけるSlirpのヒープ破損を介したゲストからホストへのエスケープ。これにより、任意のユーザースペース呼び出しが可能になる。
2025年現在、VirtualBox NATは安全か? 完全には安全ではない――コアな欠陥は残存している。代わりにブリッジドまたはホストオンリーモードを使用すべきだ。
VMエスケープからどう保護するか? ハイパーバイザーをサンドボックス化し、不要なネットワークを無効にし、異常なヒープ使用状況を監視する。