San Antonio API Security Summit 2025 に参加しよう!
San Antonio API Security Summit 2025 に参加しよう!
San Antonio API Security Summit 2025 に参加しよう!
San Antonio API Security Summit 2025 に参加しよう!
San Antonio API Security Summit 2025 に参加しよう!
San Antonio API Security Summit 2025 に参加しよう!
閉じる
プライバシー設定
ウェブサイト運営に必要なCookieや類似技術を使用しています。追加のCookieは貴社の同意がある場合のみ利用されます。同意は「Agree」をクリックすることでいただけます。どのデータが収集され、どのようにパートナーと共有されているかの詳細は、Cookieポリシープライバシーポリシーをご確認ください。
Cookieは、貴社デバイスの特性や、IPアドレス、閲覧履歴、位置情報、固有識別子などの特定の個人情報を取得、解析、保存するために使用されます。これらのデータは様々な目的で利用されます。分析Cookieによりパフォーマンスを評価し、オンライン体験やキャンペーンの効果向上に役立てます。パーソナライズCookieは、利用状況に応じた情報やサポートを通じ、貴社専用の体験を提供します。広告Cookieは、第三者が貴社のデータをもとにオーディエンスリストを作成し、ソーシャルメディアやネット上でのターゲット広告に使用します。貴社は各ページ下部のリンクから、いつでも同意の許可、拒否、または撤回が可能です。
ご送信ありがとうございます。内容を受け付けました。
申し訳ありません。フォーム送信時にエラーが発生しました。
/
/
Attacks

バッファオーバーフロー攻撃:防止と軽減の方法 第2部

記事の冒頭 前回の記事

バッファ上書きの脆弱性を検出することは非常に重要かつ価値があります。しかし、その除去には継続して認識し、安全なバッファの扱いを理解する必要があります。脆弱性を検出する一番現実的で簡単な方法は、こうした脆弱性を許さない言語を用いることです。例えばC言語は、メモリ空間へ直接アクセスできる上、厳密な型がないため、こうした脆弱性が発生しやすいです。一方、Java、Python、.NETなどの言語やプラットフォームは、特別なチェックや変更を必要とせず、オーバーフロー脆弱性のリスクが低くなっています。

バッファオーバーフロー攻撃:防止と軽減の方法 第2部

もちろん、開発言語を丸ごと変更できない場合もあります。その場合、バッファを扱う際は安全な方法を実践する必要があります。ワイヤハンドリングの関数については、安全に使える方法と、使わないほうがよい方法について議論が多くあります。

安全でない機能に選択肢があれば全てが失われるわけではありません。コンパイルや実行時に、これらの脆弱性を検出するための進展が見られます。プログラム実行時、コンパイラはしばしば「カナリア」と呼ばれるランダムな値を生成し、各バッファの後にスタック上へ配置します。いわゆる炭鉱鳥のように、これらのカナリアの値が脅威となります。カナリアの値と元の値を比較することで、バッファオーバーフローが発生したかどうかを判断できます。もし値が変われば、プログラムは戻り先アドレスが変更されるのではなく、停止したりエラーモードに入る可能性があります。

今日の一部のOSは、実行不可領域やアドレス空間配置ランダム化(ASLR)といった追加の保護機能を提供しています。実行不可領域(すなわちDEP)は、スタックや場合によっては他の構造体を、コードが実行できない領域として指定します。これにより、攻撃者はスタック上のコードを悪用できず、正常に実行されることは期待できません。

開発、コンパイラ、またはOSレベルで対策が施されていても、脆弱性が見逃され攻撃対象となる場合があります。場合によっては、攻撃が成功したこと自体がバッファオーバーフローの最初の兆候となります。この場合、まず脆弱性を特定し、問題解決のためにコードの基盤を修正する必要があります。その上で、脆弱なコードを新たに強化されたバージョンに置換することを目指します。理想的には、インターネット接続されているすべてのシステムへ自動更新で配信されることが望まれます。

しかし、こうした更新が十分な範囲をカバーするとは限りません。ソフトは、インターネットアクセスが限られるシステムで組織や個人に利用されている可能性があります。その場合は手動更新が必要です。更新情報はソフトを使用する管理者に伝え、パッチがすぐにダウンロードできる状態にする必要があります。パッチの作成と配布は、脆弱性検出にできるだけ近いタイミングで行い、ユーザーやシステムの脆弱な時間を最小限に抑えます。

安全なバッファ管理機能、コンパイラのセキュリティ機能、そして適切なOSにより、バッファオーバーフローに対してしっかりと守ることができます。こうした対策があってもエラーを継続的に特定することは重要で、ソースコードの細かい検証は手間がかかり、人の目では見逃す可能性も残ります。


Address Space Layout Randomization (ASLR)

メモリ破損の脆弱性は、プログラムが意図したメモリ領域を越え、攻撃者が制御するデータを書き込むと発生します。これによりプログラムが破壊されるか、ましてやシステム全体の制御権が攻撃者に渡る恐れがあります。Apple、Google、Microsoftなど大手企業が解消に努めているにもかかわらず、メモリ破損の脆弱性は長年ソフトを悩ませています。

これらのエラーは検出が難しく、システム全体に影響を与えるため、セキュリティ専門家はソフトの悪用を防ぎ、万が一の際の被害を制限する仕組みを設けています。理想は、脆弱なコードが残ることで、開発者にコード修正や安全な言語への書き換えの猶予を与える仕組みですが、完璧なものはありません。それでも、ASLRは最も有効な対策のひとつとされています。

アドレス空間配置ランダム化 (ASLR) は、OS向けのメモリ保護機能で、実行可能なデータの配置をランダムに行うことでバッファオーバーフロー攻撃のリスクを下げます。ASLRにより、必要なコード(例としてROP機能やモジュール)の配置が分かりにくくなるため、脆弱性そのものをなくすのではなく、悪用を困難にしています。

多くのサイバー攻撃、特にゼロデイ攻撃の成功は、攻撃者がメモリ内のプロセスや関数の状態を把握できるかどうかに依存しています。ASLRはアドレス空間を予測不能な場所に配置し、攻撃者が誤った場所を狙えば対象アプリがクラッシュして攻撃が止まり、システムに警告が送られます。

Pax Projectは2001年にLinux向けパッチとしてASLRを開発し、2007年以降VistaからWindowsにも組み込まれました。ASLR導入以前は、ファイルやアプリのメモリ配置は容易に特定できました。

VistaでASLRが導入された際、アドレス空間の候補は256箇所に増え、攻撃者が正しい実行場所を見つける確率は1/256となりました。

アドレス空間配置ランダム化

How ASLR Works:

ASLRは、実行時にプログラムやライブラリの配置に関する開発者の前提を覆すことで動作します。例えば、DEPを突破するために用いられるReturn Oriented Programming (ROP)で使われるモジュールの位置はその一例です。ASLRは、主要プログラム、動的ライブラリ、スタック、メモリにマッピングされたファイルなど、脆弱なプロセス全体のアドレス空間を混乱させます。そのため、攻撃のペイロードは被害プロセスのアドレス空間に合わせて調整する必要があります。攻撃者が無作為にメモリアドレスやエンコード済みのアドレスを全マシンに送ったとしても、ASLRが有効であれば選ばれるメモリアドレスは異なり、攻撃は成功しにくくなります。結果として、脆弱なプログラムは容易にクラッシュします。


Shortcoming Of ASLR

アドレス空間の配置をランダムにすることで、DLLの初期アドレスも起動時のランダム性に依存します。実際、これは次回再起動時に基本ライブラリのアドレスが変更されることを意味し、攻撃者はメモリ漏洩や総当たり攻撃などと組み合わせて、この弱点を突く可能性があります。

アドレス空間のランダム化の目的は、攻撃者が狙ったメモリアドレスに確実に到達するのを防ぐことです。ASLRは攻撃の捕捉に注力するのではなく、攻撃の成立可能性を低くすることを狙っています。もしシェルがランダム化により誤ったアドレスにジャンプした場合、プログラムの動作は未定義となり、例外やクラッシュ、停止、または予期しない動作を引き起こす恐れがあります。

サイバー攻撃、悪用、シェルコードに関するフォレンジック情報は、本格的な調査に不可欠です。悪用されたプロセス、メモリ領域、呼び出しの記録から、攻撃の痕跡やフィンガープリント、タグ付けが可能となります。しかし、ASLR自身は攻撃が発生しているか、いつ停止したかを把握できないため、こうした情報は得られません。

Windowsにアドレス空間のランダム化が導入されてから、実際の被害は軽減されましたが、攻撃者は常にASLRを回避する新たな技術を開発しています。回避方法としては、ASLRが適用されないモジュールでのROPチェーンの利用(例:CVE 2013-1347)、JITやNOPスプレー(例:CVE-2013-3346)、メモリ情報の漏洩などが挙げられます。


Data Execution Prevention:

バッファオーバーフローを悪用できる脆弱性を防ぐ最も簡単な方法は、プログラマーがコードを安全に保つことです。しかし、これは自動で行えるものではなく、コードの整合性を保証するための大変な作業を伴います。コード行数が増えるほど必要な時間も増加するため、現実的には他の保護手段が求められます。このため、MicrosoftはDEP(Data Execution Prevention)という機能を実装しました。

DEPは、ウイルスやその他の脅威からコンピュータを守るためのセキュリティ機能です。悪意あるプログラムは、OSや正規のプログラム用に予約されたシステムメモリからコードを実行しようとし、攻撃を試みます。こうした攻撃はプログラムやファイルに被害を与える可能性があります。

DEPは、プログラムがシステムメモリを安全に使用しているか監視し、もし不適切な使用が検出されればプログラムを終了し警告を発します。

DEPにはハードウェアベースとソフトウェアベースの両方の構成があります。

  • Hardware-Based DEP:

ハードウェアベースのDEPは、DEP実装の中で最も安全とされています。この方式では、明示的な実行コードがない限り、プロセッサがすべてのメモリ領域を「実行不可」としてマークします。DEPの目的は、実行不可領域でコードが実行されないようにすることです。

ただし、ハードウェアベースのDEPは対応できるプロセス数が限られている点が課題です。この機能は、AMDではNXサービス、IntelではXDサービスと呼ばれます。

  • Software Bases DEP

ハードウェアベースのDEPが利用できない場合は、ソフトウェアベースのDEPを使用します。この形態のDEPはWindowsに組み込まれており、プログラムが発生させる例外を検出し、その例外が正当なものかどうか確認してから実行を続けさせます。

Structured Exception Handling Overwrite Protection (SEHOP) 

構造例外処理の上書き防止機能(SEHOP)は、典型的なバッファオーバーフロー攻撃に用いられる構造例外の上書き手法の悪用を防ぎます。SEHOPを改良する目的は、悪意ある者が構造例外処理(SEH)の悪用手法を利用するのを防ぐためです。この手法は2003年9月にNGS SoftwareのDavid Litchfieldによって広められ、それ以降、SEH防止手法は攻撃の定番となりました。最新版のMetasploitシステムの約20%がSEH関連の技術を利用しており、SEHの侵害調査はブラウザ経由の脆弱性特定にも役立っています。

SEHの脆弱性は、Windowsの32ビット例外伝送機能を悪用して任意のコードを実行するために突かれます。実際には、スタックベースのバッファオーバーフローを利用して、スレッドに記録された例外ハンドラ情報を上書きすることで悪用されることが多いです。

SEHOP

Mitigating SEHOP:

SEHOPの対策としては、一般的に2つの方法が考えられます。1つ目は、実行ファイルにプラットフォームが対策を施すためのメタデータを組み込むよう、コード構成を変更する方法です。Microsoftはこの方法を採用し、Visual Studio 2003でSAFESEHと呼ばれるフラグを導入しました。しかし、実行ファイルの再構築が必要であり、例外ハンドラが画像ファイル外を指す場合には完全には対応できないため、SafeSEHはあまり魅力的ではありません。

2つ目の方法は、バイナリのメタデータに頼らず動的な制御を例外処理に追加することです。SEHOPはこの方法を採用しており、登録された例外ハンドラを呼び出す前に、スレッドの例外ハンドラリストが安全であるかを確認することで、攻撃者がSEHを悪用できないようにしています。この対策は、SEH違反時の副作用を利用することで実現されています。ほとんどのスタックベースのバッファオーバーフローが発生する際、攻撃者は例外登録レコード内の次のポインタを暗黙的に記録し、その後に例外上書き機能によりポインタが上書きされます。結果として、次のポインタが破壊され例外ハンドラの連鎖が保たれなくなります。この考え方とASLRを組み合わせることで、SEHOPはSEH違反を効果的に緩和することが可能となります。

その他、バッファオーバーフロー攻撃や脆弱性を防ぐための手法には次のものが含まれます:

  • Writing secure code: バッファオーバーフローを引き起こす脆弱性を防ぐ最善策は、安全なコードを書くことです。バッファオーバーフローにさらされやすい言語でプログラムを作成する際、開発者はリスクを認識し、可能な限り回避する必要があります。例えば、バッファのサイズを自由に決められるような機能の使用は避けるべきです。これが最良の防止策ですが、レガシーなアプリや旧型OS向けのアプリでは変更が難しい場合があります。こうした理由から、コンパイラやOSが提供する他の保護手段に頼る必要があります。
  • Making use of compiler warnings: 脆弱な機能を持つ新規ソフト作成時、コンパイラは警告を出し、安全な代替手法の使用を推奨します。開発段階で迅速に対応することが可能です。
  • Stack canaries: スタックベースのバッファオーバーフローが一般化したため、コンパイラは戻りアドレスなどスタック上の重要なデータを保護する手法を導入しました。これらのカナリアは、プログラム実行時に毎回生成されるランダムな値で、スタックに積まれ、通常は関数呼び出し前にチェックされます。もしスタックオーバーフローにより、カナリアが攻撃者の入力で上書きされた場合、プログラムは停止しエラーが発生します。

バッファオーバーフローが注目されるようになってから約20年が経過し、かつてほど効果的には機能しなくなった対策もあります。これには、スタックカナリア、アドレス空間配置ランダム化(ASLR)、コンパイラ警告、そしてスタック上でコードが実行されないようにするハードウェア変更などが含まれます。

まず、スタックベースのオーバーフロー攻撃に対する最善の保護は、安全なコーディングを実践することです。特に、攻撃者に無制限なメモリアクセスを許さないような機能の使用をやめ、隣接するメモリの値が変更されないようにすることが大切です。つまり、攻撃者が変更を試みる変数のメモリのみアクセスできれば、コード実行に予期しない影響を与えることはできません。

しかし、無制限なメモリアクセスを可能にする不安全な機能を実装しているプログラムは数多く存在し、それらすべてを安全なコーディングに則って修正することは困難です。OSメーカーは、こうした古いプログラムで悪いコーディングが任意のコード実行を招かないよう、さまざまな緩和策を講じています。とはいえ、ソフト開発の初期段階における保護こそが、バッファオーバーフロー攻撃を守る最善策です。

「バッファオーバーフロー」という用語は軽く使われがちですが、システムの安全性にとっては他のほとんどの脅威よりも深刻な問題です。最終的に、攻撃者はこの手口を用いてシステム運用に影響を及ぼす可能性があり、こうした攻撃は防御側が追いつくよりも数歩先を行っています。

FAQ

参考資料

最新情報を購読

更新日:
March 11, 2025
学習目標
最新情報を購読
購読
関連トピック