IE10 におけるメモリ保護機能の強化

Internet Explorer 10 では、メモリ保護機能に大幅な改良が加えられ、脆弱性が発見されても簡単には悪用できないようになっています。これは、時には有害にもなる Web において、ユーザーの安全を守るために役立ちます。これらの改良点によって、悪意のあるコードの難易度と開発コストは増加し、攻撃者にとって厳しい環境が作り出されます。

攻撃者が被害者のコンピューターにコードを侵入させる手法としては、ソーシャル エンジニアリング型のマルウェアが現在の主流になっています。これは主に、ここ数年の間にブラウザーの脆弱性が少なくなり、悪用するのが難しくなったためです。ところが、多くのユーザーが IE9 にアップグレードし、SmartScreen フィルター (英語) による保護機能を利用するようになるに従って、攻撃者の興味はブラウザーとそのアドオンを直接攻撃することに移ってきています。

今回の記事では、脅威となる状況について説明し、IE9 に搭載されている既存の保護機能の概要と、より高いセキュリティを提供する IE10 の新しいメモリ保護機能をご紹介していきます。

Web ブラウザーに対する攻撃

メモリ関連の脆弱性を悪用する攻撃者は、ブラウザーのコード実行パスを改ざんして、攻撃者が用意したコードを実行させることを目標としています。攻撃者がこれを達成するためには、2 つのことに成功しなければなりません。まず、攻撃対象とする被害者のコンピューター上でコードを実行できるようにする必要があります。このようなコードを用意するために使われるテクニックは、大きく 2 つに分けられます。1 つ目は、Heap Spray のような手法を使い、悪意のある独自のコードをメモリ上に配置する方法です。2 つ目は、Return Oriented Programming と呼ばれる手法により、メモリ上に既に存在するコードを選択して実行する方法です。

さらに攻撃者は、脆弱性を悪用して、コードの実行フローを設計時の状態から改ざんする必要があります。つまり、そのために悪用できるバッファー オーバーフローなどの脆弱性があることが条件となります。条件が揃うと、攻撃者によってコード パスが変更され、攻撃者が意図したコードのアドレスに "ジャンプ" させられる可能性があります。

典型的なバッファー オーバーフロー攻撃では、巧妙に細工したデータ セットをスレッドのスタックに送り込み、割り当てられているバッファーをオーバーフローさせ、他のデータ構造体を上書きするという手法が取られます。攻撃者は、例外処理レコードや関数のリターン アドレスといった構造体を上書きしようと試みます。これにより、コードのフローが攻撃者自身の指定するメモリ上の位置に変更される可能性があります。

割り当てサイズを超える量のデータがローカル バッファーに書き込まれた場合、スタックの重要な部分が上書きされ、クラッシュを引き起こす可能性があることを説明する図。攻撃者は、巧妙に細工したデータを送り込んでリターン アドレスを上書きし、コードの実行フローを任意のメモリ位置に変更してしまう。

他の攻撃の種類としては、解放後使用の脆弱性を悪用するものがあります。この場合、アプリケーションは解放済みのオブジェクトにアクセスするように仕向けられ、そのオブジェクトのメモリが別の目的に使用されます。

ブラウザーの防御機能

メモリ保護テクノロジは、攻撃者の意図が達成されるのを阻止する防御の最前線となるものです。このテクノロジの目標は、脆弱性の悪用を困難で当てにならないものにし、場合によっては不可能にすることです。メモリ保護機能は、脆弱性が悪用されて攻撃者のコードが実行される前に、攻撃を受けたブラウザー プロセスを安全に終了できるようにします。多くの場合、これによって脆弱性が悪用されて被害が発生するまでの時間を遅らせることができ、その間にベンダーは修正プログラムを作成して配布できます。

Internet Explorer で使われているメモリ関連のリスク軽減テクノロジは時代と共に進化し、新しい攻撃手法が出現して広がるのに対応して、多くの攻撃を防御できるようになっています。これまでのバージョンの Internet Explorer で使われてきた /GS コンパイラ フラグなどのさまざまな防御機能も、時間をかけてアップデートされ、強化されています。また、ForceASLR (後ほどお話しします) のように IE10 で新しく導入され、新しいオペレーティング システムの機能に依存する防御機能もあります。

コンパイル時の軽減機能

コンパイラには、ソフトウェア開発者が利用できるリスク軽減機能が用意されています。これらの機能は一般に、開発ベスト プラクティスの一環として適用する必要があるものです。Internet Explorer チームでは、セキュリティ開発ライフサイクル (SDL) の要件として、これらの軽減機能を Internet Explorer の開発に取り入れています。ソフトウェア開発者の皆さんには、コンパイル時の軽減機能の実装 (英語) を含めた独自の SDL プロセスを採用することをお勧めします。

/GS フラグは、Visual Studio .NET 2002 で初めて導入され、サポートされているすべてのバージョンの IE で使用されてきました。これは、アプリケーションのスタックにバッファー オーバーランの検出機能を追加するコンパイラ テクノロジです。このオプションを有効にすると、実行時に "カナリア" と呼ばれるセキュリティ シークレットがアプリケーションのスタック境界に追加されます。たとえば、リターン アドレスをターゲットとするバッファー オーバーフロー攻撃が試みられると、スタック バッファーとリターン アドレスの境界に配置されたカナリアが上書きされることになります。この方法を利用して、プロセスでオーバーフローの発生を検出することができます。検出時には例外が発生するので、攻撃者のコードが実行される前に安全にプロセスを終了できます。

セキュリティ シークレットがどのようにローカル変数とリターン アドレスの境界に配置されるかを示す図。関数から戻る前に、シークレットの値が元の値と比較される。一致しない場合は例外が発生し、プロセスを安全に終了できる。

保護機能の基礎となるコンセプトは、Visual Studio のバージョンが新しくなるたびに改良されてきました。Internet Explorer 9 以降で使われている最新バージョンの "拡張 /GS" では、大幅に改良されたヒューリスティックが導入され、より多くの関数を保護できるようになっています。これには、非ポインター型の配列や純粋データ構造体も含まれます。さらに、最適化機能が改良されて不必要なチェックが行われなくなり、防御にかかるパフォーマンス コストが軽減されています。

リンカー オプションである /SAFESEH フラグは、アプリケーションが登録した例外ハンドラーを参照テーブルに格納し、保護されたメモリ位置に保持するメカニズムを提供します。例外が発生すると、アプリケーションのスタックにある例外ハンドラーのアドレスが参照テーブルと照合され、検証されます。値が一致しない場合、プロセスは終了されます。

例外の登録アドレスが、ルックアップに格納された値と比較されるようすを示す図。値が一致しない場合、例外が発生してプロセスは終了する。

/SAFESEH フラグには 1 つ問題があり、プロセスを確実に保護するためには、すべての DLL モジュールでこの保護機能を有効にする必要があります。有効にしていないモジュールがあると、保護機能の効果は弱まります。Microsoft では、SDL の要件に従ってすべてのコードが SAFESEH 付きでコンパイルされるようになりましたが、サード パーティのアドオンではこのフラグが使われていない可能性があります。

/DYNAMICBASE フラグは、Address Space Layout Randomization (ASLR) と呼ばれるオペレーティング システムのリスク軽減機能にアプリケーションを組み込むリンカー オプションです。ASLR については、この記事で後ほど詳しく取り上げます。

/DYNAMICBASE フラグにも /SAFESEH の制限と同様の問題があり、この保護機能を有効にしていない DLL モジュールがあると、悪用の軽減策としての ASLR の価値は低下してしまいます。予測可能な位置にあるモジュールはすべて攻撃者のターゲットとなり得ます。そして、予測可能なターゲットが 1 つでもあれば、攻撃者にとっては十分と言えます。最近の攻撃の多くは、ASLR による保護が適用されないブラウザー アドオンをターゲットとしています。たとえば、昨年の Adobe Reader および Acrobat に対するゼロデイ攻撃では、icucnv36.dll というモジュール内の予測可能な位置にある関数が悪用されましたが、このモジュールでは ASLR が有効になっていませんでした。

実行時の軽減機能

実行時の軽減機能では、オペレーティング システムによってプロセスが保護されます。

DEP/NX は、最近の CPU に搭載されている重要なセキュリティ機能 (データ実行防止あるいは No eXecute) を利用した、オペレーティング システムによる軽減機能です。この軽減機能を利用すると、メモリ ページを実行不可能 (データ) としてマークできるようになります。そのようにマークされたメモリ ページ上のコードは、プロセッサによって拒否されます。

メモリ悪用の第 2 段階に達した攻撃者は、メモリ内のデータ ページに追加した独自のコードを実行しようと試みます。しかし、データ ページが実行不可能としてマークされていれば、攻撃者のコードの実行は失敗するため、プロセスを安全に終了できます。

DEP/NX のサポートは、IE8 で初めて既定で有効になり、IE10 でも引き続き有効になっています。

SEHOP は、例外ハンドラーの改ざん防止メカニズムを提供する実行時の軽減機能で、/SAFESEH コンパイラ フラグとよく似ています。この保護機能では、スレッドの例外ハンドラー リストの末尾にシンボリック例外レコードが挿入されます。例外の発生時には、例外ハンドラー リストの要素が順番に参照され、シンボリック レコードに到達できるかどうかがチェックされます。到達できない場合は例外ハンドラー チェーンが破損していると考えられるため、プロセスは安全に終了されます。SafeSEH とは異なり、SEHOP では、個々のモジュールによる対応は必要ありません。したがって、十分なセキュリティ フラグを使わずにコンパイルされたアドオンにも保護機能が提供されます。

SEHOP は IE9 で初めて有効になり (英語)、IE10 でも引き続き有効になっています。

Address Space Layout Randomization (ASLR) は、Windows Vista で初めて導入され、Windows 8 で大幅に改良されました。ASLR は、アプリケーションが最初にメモリに読み込まれるときにランダムなベース メモリ アドレスを割り当てる機能です。さらに、プロセス環境ブロック (PEB)、スレッド環境ブロック (TEB)、スタックとヒープなどの他のメモリ構造体も、メモリ上のランダムな位置に割り当てられます。

メモリ上のオブジェクトと関数の位置をランダム化すれば、それらがどこにあるかを攻撃者が見つけることは難しくなります。これは、Return Oriented Programming と呼ばれる手法を防ぐのに役立ちます。このランダム化は、攻撃者の荷物にダイヤル ロックで鍵をかけた状態と考えることができます。ダイヤル番号の組み合わせを知らない攻撃者は、想像するしかありません。正しい番号を 1 回で当てなければ攻撃は失敗し、プロセスは安全に終了します。

次の図は、システムの起動時にコア システム コンポーネントがランダムなメモリ アドレスに読み込まれるようすを表しています。

1 回目と 2 回目のブートでさまざまなシステム DLL の物理メモリ位置が変わることを示す図。

Windows 8 の ASLR にはたくさんの改良が加えられており、それらはすべて Internet Explorer 10 にも反映されます。

割り当てはすべて、ボトムアップでもトップダウンでも 8 ビットのエントロピによってランダム化されるようになりました。この改良により、予測可能なメモリ領域は大きく減少しています。VirtualAlloc (英語) や MapViewOfFile (英語) もランダム化の対象になります。

High Entropy Address Space Layout Randomization (HEASLR) では、さらに広い 64 ビット アドレス空間が利用され、より多くのビットがエントロピに割り当てられます。その結果、64 ビット プロセスに割り当てることのできるアドレスの数が大幅に増加します。すべての 64 ビット プロセスは、HEASLR によって利用可能になる高いエントロピに対応するように設定することができます。この機能は、リンク時に指定する (/HIGHENTROPYVA) ことも、Image File Execution Option を使用して実行時に有効にすることもできます。

既定では、64 ビット コンピューター上の Metro スタイル ブラウザーは 64 ビット モードで動作し、より広いアドレス空間を利用できるため、メモリ配置のランダム性も高まります。

ForceASLR は、おそらく Windows 8 における ASLR の最も重要な変更点と言えるでしょう。ForceASLR は、Internet Explorer 10 で使われている新しいローダー オプションで、ブラウザーによって読み込まれるすべてのモジュールの位置をランダム化するようにオペレーティング システムに指示します。このランダム化は、対象となるモジュールが /DYNAMICBASE フラグ付きでコンパイルされていなくても適用されます。ForceASLR による保護機能は、もともとは Windows 8 カーネルに追加されたものですが、今では Windows 7 の更新プログラムとしても利用できるようになりました。Windows 7 に Internet Explorer 10 をインストールすると、この更新プログラムもインストールされます。

アドオン開発者の皆さんには、この機能との互換性を確保し、ForceASLR をサポートしていない以前のバージョンの Internet Explorer でもメモリ ランダム化による保護が働くようにするために、引き続き /DYNAMICBASE フラグを使用することをお勧めします。

まとめ

今回は、Windows 8 と Internet Explorer 10 におけるメモリ保護の概要を簡単にご紹介してきました。この記事がお役に立てばさいわいです。水面下では、セキュリティを強化するために他にもさまざまな調整が加えられていますが、その多くは非常に奥深い部分に関するもので、それぞれを表す名称も付いていません。セキュリティに関してはもう少し発表することがありますので、今後の更新にご注目ください。私たちは、安全な Web ブラウジング プラットフォームの実現に向けた取り組みを引き続きて進めていきます。

- Internet Explorer 担当セキュリティ プログラム マネージャー Forbes Higman