UAF(Use-After-Free) ゆーえーえふ(ゆーずあふたーふりー)
メモリ破壊バッファオーバーフローヒープ脆弱性エクスプロイトメモリ安全性
UAFについて教えて
簡単に言うとこんな感じ!
一度返却した部屋(メモリ)に、鍵を返し忘れてこっそり入り続けるイメージだよ!プログラムが「もう使わない」と返したはずのメモリ領域を、攻撃者が乗っ取って悪用する脆弱性なんだ。ブラウザやOSへの侵入でよく使われる危険な手口だよ!
UAF(Use-After-Free)とは
UAF(Use-After-Free) とは、プログラムがいったん解放(free)したメモリ領域を、その後も参照・操作し続けてしまう脆弱性のことです。「解放後使用」とも呼ばれます。メモリ管理のミスによって生じるバグの一種で、攻撃者に悪用されると任意のコードを実行させられてしまう、非常に危険な脆弱性です。
プログラムはメモリを動的に確保(アロケート)し、使い終わったら解放(フリー)します。しかし解放後も、その領域を指す ダングリングポインタ(dangling pointer) が残っていると、プログラムは誤ってその領域を操作し続けます。攻撃者はこの隙を狙い、解放されたメモリに悪意あるデータを配置し直すことで、プログラムの制御を奪います。
UAFはWebブラウザ、PDF・Office文書ビューア、OS内部など、複雑なメモリ管理を行うソフトウェア全般で発見されており、CVSSスコア9.0超え の致命的な脆弱性として報告されるケースも珍しくありません。
UAFが発生する仕組み
UAFは以下の3ステップで成立します。
| ステップ | 内容 | 例え |
|---|---|---|
| ① Allocate(確保) | プログラムがヒープ領域にメモリを確保し、ポインタで指し示す | ホテルにチェックイン、鍵を受け取る |
| ② Free(解放) | メモリを解放するが、ポインタはそのアドレスを指したまま | チェックアウト、でも鍵を返し忘れる |
| ③ Use(再使用) | 解放済み領域を誤って参照・書き込みしてしまう | 空き部屋に不正入室、荷物をすり替えられる |
攻撃シナリオの流れ
[正常なプログラム]
obj = malloc(size) ← ①メモリ確保
ptr = obj ← ポインタをセット
free(obj) ← ②メモリ解放
※ ptr はまだ同じアドレスを指している(ダングリングポインタ)
[攻撃者の介入]
malloc(size) ← 同サイズで別データを割り当て直す
→ 解放された領域を悪意あるデータで埋める
[脆弱なプログラム]
ptr->method() ← ③解放済み領域を参照 → 攻撃コードが実行される!
C++における仮想関数テーブル(vtable)乗っ取り
C++では、オブジェクトの関数呼び出しに vtable(仮想関数テーブル) というポインタ群を使います。UAFによってvtableのポインタを偽物と差し替えると、攻撃者が用意したコードに実行を誘導できます。これが実際の攻撃で多用される典型パターンです。
歴史と背景
- 1990年代〜 C/C++の普及とともに、ダングリングポインタに起因するバグが認識されはじめる
- 2000年代前半 ブラウザの高機能化(JavaScript、DOM操作)とともにヒープ領域の操作が複雑化し、UAF脆弱性が増加
- 2010年 IE6/7のUAF脆弱性(CVE-2010-0249)を用いた「Operation Aurora」がGoogle等を標的に攻撃。UAFが国家級の高度攻撃(APT)に使われることが広く知られる
- 2012〜2016年 Chrome、Firefox、IE、Flashを標的にしたUAF脆弱性が毎年多数報告。CVSSスコア9.x台の致命的なものも頻出
- 2017年以降 Windows Kernel・macOS・Linux内部のUAFが増加。特権昇格(Privilege Escalation)の手口として多用される
- 2019年 CVE-2019-1367(IE)、CVE-2019-0808(Windows Kernel)など複数のゼロデイUAFが標的型攻撃で使われる
- 2021年以降 Rustなどメモリ安全な言語の採用が業界全体で加速。GoogleはChromiumへのRust採用を進め、Androidも同様の方針を表明
UAFと他のメモリ脆弱性の比較
| 脆弱性の種類 | 発生箇所 | 概要 | 危険度 |
|---|---|---|---|
| UAF | ヒープ領域 | 解放済みメモリの再使用 | ★★★★★ |
| バッファオーバーフロー | スタック/ヒープ | 領域外への書き込み | ★★★★★ |
| ダブルフリー | ヒープ領域 | 同じメモリを二重解放 | ★★★★☆ |
| ヌルポインタ参照 | どこでも | 無効アドレスへのアクセス | ★★☆☆☆ |
| 整数オーバーフロー | 演算処理 | 計算結果の桁あふれ | ★★★☆☆ |
対策技術の比較
| 対策 | 概要 | 効果 | 限界 |
|---|---|---|---|
| ASLR | メモリ配置をランダム化 | エクスプロイトを困難に | 情報リークと組み合わせると回避可能 |
| CFG / CFI | 制御フローの正当性を検証 | vtable乗っ取りを防止 | 実装コストが高い |
| ヒープサニタイザー | 解放済みメモリへのアクセスを検出 | 開発時のバグ検出に有効 | 本番環境では性能低下 |
| メモリ安全言語(Rust等) | 言語レベルで所有権を管理 | UAFをコンパイル時に防止 | 既存C/C++コードの書き換えコストが高い |
| GCベース言語(Java等) | ガベージコレクタが管理 | ダングリングポインタが発生しない | GCのオーバーヘッド |
関連する規格・RFC
| 規格・番号 | 内容 |
|---|---|
| CWE-416 | MITREによるUAFの共通脆弱性タイプ定義(Use After Free) |
| CWE-119 | バッファ境界外メモリ操作の上位カテゴリ |
関連用語
- ./170-buffer-overflow.md — バッファオーバーフロー:メモリ領域の境界を越えて書き込む脆弱性
- ./171-heap-spray.md — ヒープスプレー:UAFと組み合わせて悪用されるメモリ埋め尽くし攻撃技法
- ./172-aslr.md — ASLR:メモリ配置をランダム化してエクスプロイトを困難にする防御技術
- ./173-dangling-pointer.md — ダングリングポインタ:解放済みメモリを指したままになる危険なポインタ
- ./175-cve.md — CVE:脆弱性に付与される共通識別番号(例: CVE-2019-1367)
- ./176-zero-day.md — ゼロデイ脆弱性:修正パッチが存在しない状態で悪用される脆弱性
- ./177-privilege-escalation.md — 特権昇格:一般ユーザー権限から管理者権限を不正に取得する攻撃
- ./178-memory-safety.md — メモリ安全性:RustなどがUAFを言語レベルで防止する仕組み