- 何が起きた: 「Branch Target Reuse(BTR)」と呼ばれる攻撃により、一般ユーザー権限で動くコードからLinuxのrootアカウントのパスワードハッシュを、Intelの2つの実験環境で平均3分・5分で取得した。
- なぜ重要か: JITコードを解放した後もCPU内部に残る古い分岐予測を悪用し、従来の分離策だけでは防ぎにくい経路から秘密情報を読み出せることを示した。
- 次に見るべき点: LinuxやGraalVMの修正が利用中の製品へどこまで反映されているかに加え、ブラウザのサイト隔離や、JITコードを再利用するときの分岐予測の扱いが焦点となる。
オランダのアムステルダム自由大学(Vrije Universiteit Amsterdam)のVUSecと、イタリアのScuola Superiore Sant’Annaなどによる研究チームが、Linuxのrootアカウントのパスワードハッシュを数分で読み出すCPU攻撃「Branch Target Reuse(BTR)」を公開した。
Intelの2つの実験環境では、当時のUbuntuで有効だった緩和策を回避し、一般ユーザー権限で動くローカルプログラムから、平均3分と5分でハッシュを取得した。
攻撃の鍵となるのは、実行中に機械語を生成するJITコンパイラと、CPU内部に残る古い分岐予測の食い違いだ。JITが生成したコードそのものを安全に管理していても、そのコードを削除した後までCPUに残る予測情報が安全とは限らない。研究チームの公開資料
Sander Wiebing氏、Yuhui Zhu氏らによる論文は査読を経て、ACM CCS 2026に採択されている。
今回取得されたのは認証に使われるパスワードハッシュであり、平文のパスワードを復元したり、root権限そのものを奪取したりした実験ではない。それでも、本来は一般ユーザーから読み出せないはずの秘密情報が、正規のJITコード生成機能を足掛かりに漏えいした点は重要である。
消えたコードの分岐予測がCPUに残る
JITコンパイラは、JavaScriptなどのプログラムを実行しながら機械語へ変換する仕組みである。頻繁に使われる処理を高速化するためにコードを生成し、不要になればそのコードを解放して、空いたメモリー領域を別のコードへ再利用する。
JITはWebブラウザだけでなく、各種言語ランタイムやLinuxカーネルでも使われている。
一方、CPUは分岐先が確定するまで何もせず待っているわけではない。
実行するまで飛び先が分からない「間接分岐」では、CPUが過去の実行履歴を基に次の分岐先を予測し、命令を先回りして実行する。この予測には、分岐先バッファ(Branch Target Buffer、BTB)などが使われる。
予測が外れれば、先回りして計算した結果そのものは破棄される。しかし、投機的な実行中にアクセスしたデータがCPUキャッシュなどへ残した痕跡まで、完全に元へ戻るとは限らない。
Spectre系の攻撃は、こうした痕跡を観測して、本来アクセスできない秘密情報を推測する。
BTRで問題になるのは、すでに削除されたJITコードへの分岐予測がCPU内部に残り続けることだ。
まず攻撃者は、ある間接分岐からJITコードの正規の入口へ実行を移し、CPUにその分岐先を覚えさせる。
その後、そのJITコードを解放し、同じメモリー領域へ別のコードを配置する。
すると、以前はコードの正規の入口だったアドレスが、新しいコードでは命令の途中や、単なるデータが置かれた位置になる場合がある。
それでもBTBに古い予測が残っていれば、CPUは以前の分岐先がまだ有効だと予測し、その位置から投機的な実行を始める可能性がある。
例えば、機械語の中に埋め込まれた数値は、通常の実行では単なるデータとして扱われる。ところが、そのバイト列を途中から「命令」として読み始めると、まったく別の命令列として解釈できる場合がある。
攻撃者はJITへ渡すプログラムを調整し、古い分岐予測が指す位置から実行した場合に、秘密情報の読み出しにつながる命令列が現れるよう仕込む。
これは一般的な「解放後使用(Use-after-free)」とは仕組みが異なる。
ソフトウェア上のポインタが壊れて、解放済みのメモリーへ誤ってアクセスするわけではない。古いアドレスを覚えているのは、CPU内部の分岐予測器である。
新しいコードが通常どおり正しく実行できることと、過去の分岐予測によってコードの途中へ投機的に入り込まれないことは、別の問題なのである。 論文の攻撃原理と基礎実験(第4・5節)
非特権で使えるcBPFからrootハッシュを読み出す
Linuxで一連の攻撃を実証するために使われたのが、クラシックBPF(cBPF)のJITコンパイラである。
cBPFは、システムコールを制限するseccompや、ネットワークパケットを選別するソケットフィルタなどで使われる小さなプログラム実行環境だ。
より高機能なeBPFについて一般ユーザーからの利用を制限しているシステムでも、cBPFは非特権プログラムから利用できる。
研究チームはcBPFプログラムをseccompフィルタとして導入し、JITによって生成された機械語のメモリー領域が解放・再利用される仕組みを攻撃へ利用した。
実験環境はUbuntu 24.04、Linuxカーネル6.14.0-27で、CPUにはCore i9-14900KのRaptor Coveと、Core Ultra 9 285KのLion Coveを使用した。
root権限やメモリー破壊の脆弱性をあらかじめ必要とせず、ローカルで実行する非特権コードから攻撃している。
ただし、インターネット越しに外部から直接rootパスワードを盗み出した実験ではない。
認証に必要な秘密情報は、認証処理が行われる際にプロセスのメモリーへ読み込まれる。
今回の標的となったのは、ユーザーを切り替えるsuコマンドだった。su rootを実行すると、rootアカウントのパスワードハッシュがプロセスのメモリーへ読み込まれる。
攻撃では、まずLinuxカーネルが管理するタスク一覧をたどってsuプロセスを探し出した。
その後、ページテーブルなどのメモリー管理情報を順に読み出し、最終的にrootのパスワードハッシュが保存されているメモリー領域へ到達した。
ここで、論文に示された「漏えい速度」の数字は分けて読む必要がある。
論文第6.1節の表2にある毎秒5.7KBと5.4KBは、攻撃を構成する基本処理の実行時間や成功率から算出した推定値である。
一方、秘密情報の保存場所を探し出し、実際にデータを読み出す一連の攻撃で測定された速度は、両CPUとも平均で毎秒8バイトだった。
実際の攻撃では、候補となる値ごとに分岐予測を再び訓練する処理や、キャッシュからデータを追い出す処理なども必要になる。このため、基礎実験から算出した毎秒数KBという値を、そのまま現実の攻撃速度として扱うことはできない。
それでもrootハッシュの取得は、Raptor Coveで平均3分、Lion Coveで平均5分で完了した。
メモリー全体を順番に読み出すのではなく、Linuxの管理情報に含まれるポインタをたどりながら、必要な小さな標的へ直接近づいていくためだ。
論文の時間内訳では、攻撃に必要な共有の大きなメモリーページを探す処理が所要時間の多くを占めている。
そのため、3分・5分という数字はすべての環境で再現されるものではなく、搭載メモリー量やシステムの使用状況などによって変わる。
パスワードハッシュを取得できれば、候補となるパスワードからハッシュを計算し、盗んだ値と照合するオフライン攻撃の材料にはなる。
ただし、そこから実際のパスワードを割り出せるかどうかは、パスワードの強さや使用されているハッシュ方式に左右される。
今回の研究が実証したのは、その前段階にある本来保護されているハッシュ値の漏えいである。
Linux・SpiderMonkey・GraalVMでは実証できた範囲が異なる
研究チームは、LinuxのcBPF、Firefoxで使われるJavaScriptエンジンSpiderMonkey、OracleのGraalVMという3種類のJIT環境を調査した。
ただし、3つすべてで同じレベルの攻撃が成功したわけではない。
JITコードを解放して同じアドレスを再利用したときに、CPUの古い分岐予測がどの程度残るかは、各JITエンジンのメモリー管理やコンパイル、ガベージコレクションなどの動作によって変わった。
次の表は、CCS 2026論文の第6.1〜6.3節と第7節について、「攻撃に必要な仕組みを確認できたか」「コード再利用後も予測が残ったか」「最終的に秘密情報の取得まで実証したか」という観点で整理したものだ。速度の優劣を比較する表ではない。比較の根拠となる論文
| 対象と実験条件 | 確認されたこと | 秘密取得までの実証と限界 |
|---|---|---|
| Linux cBPF:Ubuntu 24.04、カーネル6.14.0-27、Intel Raptor Cove/Lion Cove | JITコードを再利用した後も古い分岐予測が残り、機密情報の読み出しへつなげられた | rootパスワードハッシュを取得する一連の攻撃を実証。通常設定で平均毎秒8バイト、取得まで平均3分/5分 |
| SpiderMonkey:Firefox 143の単体JavaScript実行環境 | Intel CPUでコードの解放・再割り当て後にも、平均6〜7個の古い分岐予測が残った | 漏えい速度は毎秒36/62バイト程度と推定。Firefoxブラウザ全体から秘密情報を盗む一連の攻撃は未完成 |
| GraalVM:GraalPyを使ったx86-64環境、Intelの2種類のCPU | メモリーアクセスの範囲制限を飛び越えられる命令列と、コードのアドレス再利用を確認 | 解放から再利用までの間に予測が消え、実際の秘密情報の漏えいには至らなかった |
SpiderMonkeyについては、Intel CPUだけでなくAMD Zen 4やArm Cortex-A76、Cortex-X3でも調査した。
しかし、これらの環境ではコードを再利用した後まで攻撃に必要な分岐予測が残らなかった。
GraalVMでも、JITコンパイルやガベージコレクションの過程で多数の分岐が実行されるため、攻撃に使いたい古い予測が、その後の処理によって消されていた。
研究チームは、GraalVMで確認された制約が根本的な防御とは限らないとしている。しかし、現時点で成立していない一連の攻撃を、Linuxと同じように「実証済み」とみなすことはできない。
CPU単体の基礎実験で古い分岐予測を再利用できたことと、実際のOSやブラウザ環境で秘密情報の取得まで成功したことは分けて考える必要がある。
AMD製CPUも基礎実験には含まれているが、Linuxでのrootハッシュ取得実験には使われていない。
論文では、その理由として、AMDのAutoIBRSを利用する環境では、今回対象となったLinuxカーネル内部の間接分岐予測が攻撃に使えない実装になっていることを挙げている。
したがって、Intel環境で成功したLinuxのrootハッシュ取得を、そのままAMDやArm環境にも当てはめることはできない。
「定数隠蔽」だけでは防げず、別の経路から命令を埋め込めた
cBPFには、攻撃者が数値データの中へ任意の機械語を埋め込みにくくする「定数隠蔽(constant blinding)」と呼ばれる強化策がある。
JITコードに埋め込む数値をそのまま機械語へ残さず、ランダムな値との演算へ置き換えることで、攻撃者が狙ったバイト列を生成しにくくする仕組みだ。
しかし研究チームは、定数そのものではなく、分岐命令が「どれだけ先へ飛ぶか」を表すオフセットへ命令列を埋め込む方法を考案した。
通常の位置から実行すれば正当な分岐命令の並びだが、数バイトずれた位置から読み始めると、攻撃に使える別の命令列として解釈される。
この2つ目の攻撃では、定数隠蔽を有効にした状態でも、両方のIntel CPUで毎秒10バイトの情報を読み出し、5分以内にrootハッシュを取得できた。
定数を隠すだけでは、JITによって生成されるすべてのバイト列を攻撃者の制御から外せるわけではないことを示している。定数隠蔽を回避した実験(論文第7.2節)
IBTでも条件次第では投機実行を完全には止められない
Intelには、間接分岐が正規の着地点へ移っているかを検査するIndirect Branch Tracking(IBT)という仕組みがある。
研究では、Raptor Coveの場合、IBTによる検査が完了する前に1命令だけ投機的に実行できた。一方、より新しいLion Coveでは、このタイミングの隙間は確認されなかった。
ただし、これだけで問題が完全に解消するわけではない。
攻撃者がJITコードの中に、IBTが正規の入口として認める命令を生成できれば、古い分岐予測の着地点そのものを有効な入口に見せることができる。
論文では、検査前の投機実行を許さないIBTと定数隠蔽を組み合わせることを強力な防御と評価している。ただし、今後登場するすべてのJIT実装に対して安全性を保証するものではない。
なお、今回実験に使ったUbuntu環境では、IBTは標準では有効になっていなかった。
Linuxはコード再利用時に古い分岐予測を破棄する
Linux側では、BTRへの対策として、JITコードのメモリー領域を再利用するときに古い分岐予測を破棄する仕組みが導入された。
研究チームの説明によると、x86では、以前cBPFやeBPFコードが実行されたメモリー領域をcBPFが再利用する際に、全CPUコアへ間接分岐予測バリア(IBPB)を実行する。
1つのコアだけで予測を消去しても、別のコアに以前の分岐先が残っている可能性があるためだ。
この修正には2件のCVEが割り当てられた。
CVE-2026-64508は、BPF JITのメモリーを再利用するときに予測情報を消去できるようにするための基盤を追加する。
CVE-2026-64507は、x86でIBPBによる消去を有効にする修正である。
後者はSpectre-v2の緩和策を利用している場合に働き、BPFの呼び出し側ですでにretpolineによる間接分岐対策が行われている場合には、追加の消去を有効にしない。
つまり、あらゆる環境で一律に同じ方法で分岐予測を消去する仕組みではない。
OracleはGraalVMのコード配置をランダム化
OracleはLinuxとは異なる方法で対策した。
GraalVMでは、JITコードを配置する場所をランダム化し、一度解放されたアドレスへ攻撃者が狙ったコードを再び配置しにくくする変更を導入した。
この修正は8月19日にGraalVMの開発ブランチへ取り込まれた。
Linuxが「古い分岐予測を消す」ことで対処するのに対し、GraalVMは「以前と同じアドレスを再利用しにくくする」ことで攻撃条件を崩す。BTRへの対処方法は、ソフトウェアによって異なる。
Firefoxではサイト隔離も重要な防御になる
Webブラウザでは、攻撃者のコードと秘密情報を同じプロセスへ置かないことも重要な防御となる。
Mozillaのサイト隔離は、異なるWebサイトを別々のプロセスへ分離する仕組みである。
BTRのような投機実行攻撃では、攻撃コードと標的となる秘密が同じアドレス空間に存在しなければ、攻撃できる範囲を大きく制限できる。
論文では、Firefoxのデスクトップ版ではサイト隔離が導入されている一方、モバイル環境では展開が完全ではないと区別している。MozillaはIBPBを使った対策も検討したが、現在はサイト隔離の完成と展開を優先しているという。
そのため、「悪意のあるWebページを開くだけで、Firefoxの別タブにある秘密を盗める」と一般化するのは適切ではない。
今回の研究でSpiderMonkeyに対する攻撃部品は確認されたものの、Firefoxブラウザ全体を使った一連の秘密窃取までは実証されていない。
Intelは「新しいハードウェア脆弱性ではない」と評価
Intelは10月1日、BTRについて公式見解を公開した。
Intelは、今回報告された挙動について、Branch History Injection(BHI)やIntra-mode Branch Target Injection(IMBTI)を含む既存のSpectre-v2関連の指針で対処できるとしている。
そのため、BTRを新たなIntel固有のハードウェア脆弱性とは位置付けず、新しいIntel専用の緩和機能も必要ないとの立場を示した。
一方でIntelは、BPF JITに対する追加の防御策をLinuxへ提供し、利用者にはOSを最新の状態へ更新するとともに、既存のSpectre-v2関連指針を適用するよう勧めている。
このIntelの評価と、研究そのものの新規性は分けて考える必要がある。
従来のSpectre-v2対策では、異なる権限領域などから分岐予測を汚染する攻撃への対策が進められてきた。
BTRが利用するのは、攻撃対象となる分岐が以前に正規に使った分岐先そのものである。
JITコードが削除され、同じアドレスへ別のコードが配置されても、CPU内部には以前の分岐先が残っている場合がある。
研究チームが実証したのは、「かつて正しかった分岐先」を、コードが入れ替わった後も安全な情報として扱ってよいのかという問題である。
既存のCPU機能を使って対策できることと、既存のソフトウェアが必要な場面ですでにその機能を使っていたことは、同じ意味ではない。
修正は研究公開より前から進められていた
対策が始まったのは、研究が一般公開された後ではない。
論文によると、研究チームは2025年4月にCPUベンダーとLinux開発者へ問題を通知し、一連の攻撃を完成させた後の2026年5月に追加の結果を共有した。
Linuxに関する2件のCVEは7月25日に公開され、OracleのGraalVM向け変更は8月19日にマージされた。
研究が一般公開された9月29日は、ベンダーとの調整や修正作業が進んだ後にあたる。
LinuxのCVE情報では、修正を含む最初のバージョンとして、6.1系列では6.1.183、6.6系列では6.6.145、6.12系列では6.12.97が挙げられている。このほか6.18.39、7.1.4、7.2も記載されている。
ただし、Linuxディストリビューションは修正を独自に古いカーネルへ取り込む場合がある。
そのため管理者は、上流Linuxのバージョン番号だけで安全かどうかを判断するのではなく、実際に利用しているディストリビューションのカーネルパッケージに、CVE-2026-64507とCVE-2026-64508への修正が含まれているかを確認する必要がある。
GraalVMについても、開発ブランチへ修正が取り込まれたことと、自分が利用している配布版へその修正が反映されていることは別に確認したい。
JITコードは「生成した瞬間」だけ守ればよいわけではない
JITやサンドボックスを開発する側にとって、BTRが示した課題はより長期的なものになる。
Intelのランタイム向け防御指針では、秘密情報と同じアドレス空間で実行されるコードについて、JITやAOTコンパイラだけでなく、ランタイム環境やホストプロセスを含めて投機実行攻撃への対策を行うよう求めている。また、可能であればプロセス分離を優先するよう推奨している。
BTRが示したのは、JITが安全な機械語を生成できるだけでは十分ではないということだ。
そのコードを解放した後にCPU内部へどのような予測情報が残るのか。同じアドレスを別のコードへ再利用すると、その予測が新しいコードに対してどのような意味を持つのか。そこまで含めて検証する必要がある。
JITの安全性は、生成された命令列だけを見るのではなく、そのコードが生成され、実行され、解放され、同じメモリー領域が次のコードへ渡されるまでの一連の過程として考える必要がある。



