高度な攻撃手法

バッファオーバーフロー ばっふぁおーばーふろー

メモリ破壊スタック破壊シェルコード脆弱性エクスプロイトASLR
バッファオーバーフローって何?

簡単に言うとこんな感じ!

コップに水を入れすぎてあふれちゃうイメージだよ!プログラムが「ここに10文字分のデータを置いておく」って決めた場所に、100文字のデータを無理やり押し込むと、はみ出したデータが隣の大事な領域を上書きしちゃうんだ。それを悪用して攻撃者が「好きなコードを実行させる」ことができる怖い脆弱性なんだよ!


バッファオーバーフローとは

バッファオーバーフロー(Buffer Overflow)とは、プログラムが確保したメモリ領域(バッファ)の境界を超えてデータを書き込んでしまう脆弱性、およびそれを悪用した攻撃手法のことです。C言語やC++など、メモリ管理を手動で行う言語で書かれたプログラムに多く見られます。

バッファとは「一時的にデータを置いておく箱」のようなもので、たとえば「ユーザー名は最大20文字まで」と決めた領域がそれにあたります。プログラマーがこの境界チェックを怠ると、20文字を超えた入力が隣接するメモリ領域を上書きしてしまいます。この「はみ出し」によって、攻撃者が意図した任意のコードを実行させる(任意コード実行) ことが可能になります。

1988年のMorrisワームが初めてこの脆弱性を大規模に悪用して以来、数十年にわたって重大なセキュリティインシデントの原因であり続けています。現在でもCVE(共通脆弱性識別子)データベースの上位常連であり、システム発注側も「使用言語・フレームワークのセキュリティ対策」として認識すべき重要な概念です。


バッファオーバーフローの仕組み

メモリレイアウトと何が起きるか

プログラムが動作するとき、メモリは大きく分けて以下の領域に分かれています。

領域役割攻撃との関係
スタック関数の引数・ローカル変数・戻りアドレスを置く最も狙われやすい(スタックオーバーフロー)
ヒープ動的に確保されるデータを置くヒープオーバーフローとして悪用される
テキスト領域プログラムの命令コード通常は書き込み不可
データ領域グローバル変数などBSS/データセグメントオーバーフロー

最も古典的な攻撃はスタックオーバーフローです。スタック上にある「関数の戻りアドレス(処理が終わったらどこに戻るか)」を攻撃者が用意した悪意あるコード(シェルコード)のアドレスで上書きすることで、プログラムが攻撃者の意図した処理を実行してしまいます。

通常時のスタック:
┌────────────────────┐ ← 高位アドレス
│   戻りアドレス      │  ← 関数を呼び出した場所に戻るためのアドレス
├────────────────────┤
│   保存済みレジスタ  │
├────────────────────┤
│   ローカル変数      │
│   [buf: 16バイト]  │  ← ここに入力データを格納
└────────────────────┘ ← 低位アドレス(書き込みはここから上方向)

攻撃時(20バイト以上の入力を流し込む):
┌────────────────────┐
│  ★悪意のアドレス★  │  ← 戻りアドレスが上書きされた!
├────────────────────┤
│   (上書きされた)  │
├────────────────────┤
│  AAAAAAAAAAAAAAAAA │  ← bufを超えてあふれた入力データ
│  AAAA...シェルコード│
└────────────────────┘

覚え方

バッファ(箱)にオーバーフロー(あふれ)させてリターン(戻り先)を乗っ取る」——箱・あふれ・乗っ取りの3ステップで覚えよう!

攻撃の種類

攻撃の種類標的特徴
スタックバッファオーバーフロースタック上の戻りアドレス古典的・最も有名
ヒープバッファオーバーフローヒープの管理構造現代的なブラウザ攻撃に多い
整数オーバーフロー起因バッファサイズ計算サイズ計算が誤ることでバッファを小さく確保させる
フォーマット文字列攻撃printfなどの書式厳密にはオーバーフローではないが同系統の危険

歴史と背景

  • 1972年 — 米国防総省のCSCレポートで「バッファオーバーフロー」の危険性が初めて文書化される
  • 1988年Morrisワームがfingerdの脆弱性(スタックオーバーフロー)を悪用。インターネット上のマシンの約10%(約6,000台)に感染し、初の大規模インターネットワームとして歴史に刻まれる
  • 1996年 — Aleph One(Elias Levy)が雑誌Phrackに「Smashing the Stack for Fun and Profit」を発表。攻撃手法を体系的に解説し、セキュリティ研究の転換点となる
  • 1998〜2003年 — WindowsのIIS・sendmail・OpenSSHなど主要サーバーソフトで相次いで発見、Code RedSlammerワームが猛威を振るう
  • 2000年代以降 — コンパイラ・OSレベルの緩和策(後述)が普及。単純なスタックオーバーフローは成功しにくくなるが、ヒープオーバーフローやROP(Return-Oriented Programming)などより高度な手法に進化
  • 現在 — ブラウザ・スマートフォンアプリ・IoT機器でも継続して発見。CWE(共通脆弱性タイプ)のCWE-119/CWE-121/CWE-122として分類・管理されている

防御策と緩和技術

現代のOSやコンパイラには、バッファオーバーフロー攻撃を困難にする複数の防衛レイヤーが組み込まれています。

バッファオーバーフロー対策の多層防御 ① ASLR(アドレス空間配置ランダム化) スタック・ヒープ・ライブラリのアドレスを起動ごとにランダム化 → 攻撃者がアドレスを予測できなくする ② スタックカナリア(Stack Canary) 戻りアドレスの手前にランダムな「番兵値」を配置 → 関数終了時に値が変わっていたら攻撃を検知して停止 ③ DEP / NX ビット(実行不可メモリ) スタック・ヒープ領域を「実行不可」に設定 → シェルコードを書き込んでも実行できない ④ 安全なコーディング(根本対策) gets()→fgets() / strcpy()→strncpy() / 境界チェックの徹底 / RustやGoなど安全な言語を使う
防御技術正式名称効果限界
ASLRAddress Space Layout Randomizationアドレス予測を困難に情報リークと組み合わせると回避される
スタックカナリアStack Canary / Stack Cookie改ざん検知番兵値が漏洩すると無効化される
DEP/NXData Execution Prevention / No-eXecuteシェルコード実行を防止ROPによって回避される
SafeStackLLVM SafeStackスタックを2つに分離コンパイラサポートが必要
ROP対策(CFI)Control Flow Integrity制御フローの整合性を検証オーバーヘッドが発生

ROPとは?(進化した攻撃)

DEP/NXによって「新しいコードを注入して実行」が難しくなると、攻撃者はROP(Return-Oriented Programming)という手法を開発しました。これはプログラム内にもともと存在する小さなコード断片(「ガジェット」と呼ぶ)をつなぎ合わせて、任意の処理を実現するというパズルのような攻撃です。DEP/NXでは防げないため、CFI(制御フロー整合性)が重要になっています。


関連する規格・RFC

規格・番号内容
CWE-119Improper Restriction of Operations within the Bounds of a Memory Buffer(バッファ境界外操作の不適切な制限)
CWE-121Stack-based Buffer Overflow(スタックベースのバッファオーバーフロー)
CWE-122Heap-based Buffer Overflow(ヒープベースのバッファオーバーフロー)
CVE共通識別子NVD(National Vulnerability Database)で個別の脆弱性を追跡・管理する仕組み

関連用語

  • 任意コード実行(ACE) — 攻撃者が任意のプログラムコードを標的システム上で実行できる状態
  • スタックスマッシング — スタック領域を意図的に破壊するバッファオーバーフロー攻撃の別称
  • ASLR — アドレス空間をランダム化することでバッファオーバーフロー攻撃を困難にする防御技術
  • DEP(データ実行防止) — メモリ領域に「実行不可」フラグを立ててシェルコードの実行を防ぐ仕組み
  • CVE — 公開された脆弱性に一意のID番号を付与して管理する共通識別システム
  • ゼロデイ脆弱性 — パッチが提供される前に悪用される未知の脆弱性
  • ペネトレーションテスト — 擬似的に攻撃を仕掛けてシステムの脆弱性を発見するセキュリティ検査
  • メモリセーフ言語 — RustやGoのようにバッファオーバーフローをコンパイラレベルで防ぐ設計の言語