Rowhammer(DRAMビット反転)
権限のないプロセスがDRAMの物理的な弱点だけで全メモリを書き換える攻撃を、電荷リークの原理からページテーブル改変、TRR・ECCが破られた理由まで最短で理解できる。
- DRAMの同じ行を高速に叩くと、電荷結合と漏れで隣接行のビットが反転する。ソフトウェアだけで物理メモリを変え、Project Zeroはサンドボックス脱出とカーネル権限昇格を実証した。
- 攻撃の核心はページテーブルエントリ(PTE)1ビットの反転。物理アドレスを指す番地が書き換わり、自分のプロセスが自分のページテーブルへ書き込めるようになると、全物理メモリへの読み書きが手に入る。
- ECCは複数ビット反転で、TRRはTRRespass・Blacksmithの多面/非一様ハンマーで破られた。微細化で電荷が減るほど閾値も下がり、ハードウェアの物理限界がソフトの権限境界を侵す構造的な問題である。
何が起きたか(影響範囲・深刻度)
Rowhammerは、DRAM上のある行(row)を高速で繰り返しアクセスすると、物理的に隣接した行の記憶ビットが電気的に反転してしまう現象、およびそれを悪用する攻撃の総称です。2014年にKimらの論文「Flipping Bits in Memory Without Accessing Them」(ISCA 2014)が現象を体系的に報告し、テストしたDDR3モジュールの大多数でビット反転を観測しました。翌2015年3月、GoogleのProject Zero(Seaborn・Dempsky・Dullien)が2つの実働エクスプロイトを公開し、これが「バグ」ではなく「悪用可能な脆弱性」であることを決定づけました。
深刻度が高いのは、権限のないユーザー空間プロセスが、ソフトウェアのバグを一切突かずにカーネルやハイパーバイザの管理する物理メモリを改変できる点です。代表的なCVEはNaClサンドボックス脱出の CVE-2015-0565(CLFLUSH命令の悪用)で、NVDではCVSS v2・v3ともに最高値の10.0(v2はHIGH、v3.1はCRITICAL)と評価されています。ただしRowhammerは単一CVEに収まらず、Rowhammer.js・Drammer(Android)・RAMBleed(情報漏洩)・TRRespass・Blacksmith と派生が続く「脆弱性のクラス」です。影響はサーバー・PC・スマートフォンからクラウドの共有ホストまで及び、ソフトウェアパッチだけでは根絶できません。
Rowhammerは特定ベンダのファームウェア不具合ではなく、DRAMセルを微細化した結果として現れる物理的な副作用です。だからこそ、CPUやOSの世代が変わっても同じ原理が繰り返し問題になり続けます。
脆弱性の原理(なぜ起きるか)
DRAMのセルは1個のキャパシタ(電荷の有無で0/1を保持)と1個のアクセストランジスタから成り、行を選ぶワード線(word line)と列を読むビット線(bit line)が格子状に走ります。ある行を読むには、その行のワード線を活性化(ACTIVATE)してキャパシタの電荷をセンスアンプに移し、再度書き戻します。問題は2つの物理的性質から生じます。
- 電荷リーク: キャパシタは時間とともに自然放電するため、DRAMは一定周期(標準で64ミリ秒)ごとに全行をリフレッシュ(読んで書き戻す)して内容を保つ。
- ディスターバンス(disturbance): あるワード線を活性化・充放電すると、寄生的な容量結合や電荷注入によって、物理的に隣接する行(victim row)のキャパシタからわずかに電荷が漏れる。
攻撃者が対象行(aggressor row)を1リフレッシュ周期のあいだに何万回も活性化すると、隣接行の電荷漏れが積み重なり、次のリフレッシュが来る前に閾値を割ってビットが反転します。1回の活性化あたりの漏れは微小でも、activation回数 × 1回あたりの漏れ量 がリフレッシュ間隔内で臨界電荷を超えれば反転が成立する、という単純な累積の勝負です。
反転を起こすには、victim行を確実にリフレッシュ周期内で叩き切る必要があります。素朴に同じアドレスを読むだけではCPUのキャッシュに載って実DRAMへ到達しないため、初期の手法は CLFLUSH 命令でキャッシュ行を追い出し、DRAMへの生アクセスを強制しました。
# 概念コード(両側ハンマー: victim行を上下のaggressorで挟む)
loop:
read(addr_A) # aggressor 行 A を活性化
read(addr_B) # 反対側の aggressor 行 B を活性化
flush(addr_A) # キャッシュを追い出し次回も実DRAMへ
flush(addr_B)
goto loop # リフレッシュ周期内に数万回反復
プロセスが進みセルが小さくなるほど蓄えられる電荷も減り、隣接セルとの距離も縮まります。反転に必要なハンマー回数は世代ごとに下がる傾向にあり、DDR4以降はより少ない活性化で反転が観測されます。
エクスプロイトの流れ(どう悪用されるか)
横にスクロール
物理的な「どこかのビットが反転する」だけでは攻撃になりません。鍵は、攻撃者にとって都合の良い場所のビットを反転させ、その結果を権限昇格につなげることです。Project Zeroのカーネル昇格は次の概念で進みます(実装詳細やそのまま動くコードは割愛)。
- 偵察: 自プロセスの多数のページをハンマーし、「どの物理オフセットが、どの向き(0→1/1→0)に反転しやすいか」を記録する。反転は決定論的ではないが、セル固有の弱点として再現しやすい箇所がある。
- メモリ配置(グルーミング): 反転しやすいビットの位置に、ページテーブルエントリ(PTE)が来るようメモリを整える。Linuxでは大量のメモリをマップし、ページテーブルが物理的にその近傍へ割り当てられるよう仕向ける(page-table spraying)。
- 反転の誘発: 対象を挟む両側の行をハンマーし、PTE内の物理フレーム番号(PFN)を指すビットを1つ反転させる。
- 昇格: 反転により、あるPTEが「攻撃者プロセス自身のページテーブルを含む物理ページ」を指すよう書き換わる。するとプロセスは自分のページテーブルに書き込めるようになり、任意のPTEを設定して全物理メモリへの読み書きを獲得する。これはカーネルメモリの改変、すなわち完全な権限昇格を意味する。
もう一つのCVE-2015-0565では、Google Native Client(NaCl)のサンドボックス内から反転を起こし、検証済み命令列の制約を崩してサンドボックス外へ逃れました。緩和は「サンドボックス内で CLFLUSH を発行させない」ことでした。いずれも共通するのは、ソフトウェアの論理には一切穴がないのに、論理を支える物理の土台を揺さぶって境界を破るという構図です。
クラウドの共有ホストやブラウザ内でも成立し得ます。Rowhammer.jsはJavaScriptからキャッシュ追い出しだけで反転を起こし、DrammerはAndroidでルート権限を決定論的に奪取しました。物理メモリを共有する限り、テナント間・タブ間の隔離も脅かされます。
修正と対策(何を変えたか、緩和策とその限界)
Rowhammerはソフトウェア単体では塞ぎきれないため、対策はハードウェア・ファームウェア・ソフトの多層で積み重ねられてきました。主要な緩和と、それぞれが破られた経緯を整理します。
| 緩和策 | 仕組み | 限界・回避 |
|---|---|---|
| リフレッシュ間隔短縮 | 64msから32msへ半減し、電荷が閾値を割る前に書き戻す | 帯域と電力を消費。より少ないハンマーで反転する世代には不十分 |
| TRR(Target Row Refresh) | 活性化の多い行を検知し、隣接victim行を追加リフレッシュ | TRRespass(2020)の多面ハンマー、Blacksmith(2021)の非一様パターンで回避 |
| ECC(誤り訂正符号) | 1ビット誤りを訂正、2ビットを検出する冗長ビット | ECCploit(2019)が示すとおり複数ビット同時反転で貫通。反転自体は防げない |
| pTRR / MAC・行カウンタ | 行ごとの活性化回数を数え閾値で介入する | カウンタ資源に限りがあり、多数の行を分散して叩くと追随できない |
TRR(Target Row Refresh)はDDR4世代でメモリ内蔵の防御として広く搭載されました。頻繁に叩かれる行を検出し、その隣接行を通常より早くリフレッシュする発想です。しかしTRRの検出器が追跡できる「同時に監視できる行数」には上限があり、TRRespass(2020)はその上限を超える数の行を同時に叩く「多面ハンマー(many-sided hammering)」でTRRをすり抜けました。さらにBlacksmith(2021, ETH Zurich)は、活性化の頻度・位相・振幅を変えた非一様なパターンを探索し、テストした40枚すべてのDDR4チップで反転を再現しました。TRRespassが42枚中13枚だったのに対し、非一様化の威力を示した結果です。
ECC(Error-Correcting Code)は1ビット誤りを訂正できますが、Rowhammerは同一語内で複数ビットを反転させ得るため、ECCploit(2019)は訂正しきれない多ビット反転を狙って回避可能だと示しました。ECCは反転の一部を吸収するハードルにはなっても、根本原因である電荷漏れそのものは止められません。より本質的な対策として、ロジック側で確率的に行をリフレッシュするPARA(Probabilistic Adjacent Row Activation)や、後継規格でのオンダイECC・改良版行カウンタ(例えば新世代のRFM: Refresh Management)が導入されつつありますが、微細化との追いかけっこは続いています。
アプリ開発者が反転そのものを防ぐのは困難ですが、リスク低減は可能です。信頼境界を越えるコードのサンドボックスを強化し、共有ホストではECC付きメモリと最新ファームウェアを前提とし、機密を扱うプロセスは物理的に隔離する。攻撃には持続的な高頻度アクセスが要るため、異常なメモリアクセス監視も一定の抑止になります。
教訓(一般化できる原則)
Rowhammerが突きつけるのは、抽象化の下にある物理は、いつか抽象化の約束を裏切るという原則です。プログラマはメモリを「書いた値がそのまま保たれる理想の配列」として扱いますが、その理想は電荷という物理量の上に辛うじて成り立っています。物理の限界(微細化による電荷減少と結合)が閾値を割った瞬間、ソフトウェアの権限境界という論理的な約束が、一切のバグなしに破れます。
- セキュリティ境界はスタックの一番下まで疑う: OSやサンドボックスの論理が正しくても、それを支えるハードウェアが前提を満たさなければ境界は崩れる。脅威モデルにハードウェアの物理特性を含める。
- 単一の防御を信頼しない(多層防御): TRRもECCも単独では破られた。リフレッシュ強化・行監視・ECC・隔離を重ね、どれか1つの突破が即・全面突破にならないよう設計する。
- 緩和はいたちごっこである前提で運用する: 新しい防御は新しい攻撃を招く。ファームウェア更新とメモリ世代の選定を継続的な運用課題として扱い、「一度直せば終わり」と考えない。
Rowhammerと同じく「ハードウェアの物理・実装が論理的な隔離を破る」系譜には、投機的実行を悪用するSpectre/Meltdownがあります。前提となるメモリ管理やページテーブルの仕組みはOS、隔離とサンドボックスの設計思想はセキュリティ、DRAMやキャッシュの物理はハードウェアの各トピックも参照してください。
脆弱性の解剖の記事ガイド
Rowhammer(DRAMビット反転)を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
Rowhammer
比較で見る軸
難易度: advanced / カテゴリ: 脆弱性の解剖 / タグ数: 6
導入後に効く点
攻撃の核心はページテーブルエントリ(PTE)1ビットの反転。物理アドレスを指す番地が書き換わり、自分のプロセスが自分のページテーブルへ書き込めるようになると、全物理メモリへの読み書きが手に入る。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- 脆弱性の解剖
- タグ数
- 6
判断チェックリスト
- 自社の用途が「Rowhammer / DRAM」に近いか確認する。
- 強みである「DRAMの同じ行を高速に叩くと、電荷結合と漏れで隣接行のビットが反転する。ソフトウェアだけで物理メモリを変え、Project Zeroはサンドボックス脱出とカーネル権限昇格を実証した。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。