IEの「Delay Free」、「解放後使用」の脆弱性利用の攻撃を軽減

2014年6月公開の Microsoft のセキュリティ更新プログラムで、「isolated heap(隔離されたヒープ)」と呼ばれる改善がありましたが、7月のセキュリティ更新プログラムでも、Internet Explorer(IE)に関するいくつかの改善が確認されています。なかでも最も興味深く、また賢明だと思われるのは、IE に存在する「Use After Free(解放後使用)」の脆弱性を利用した攻撃を軽減するように設計された改善策です。本稿では、この改善策を「delay free」と呼びます。この改善策により、参照数が 0 の場合、IE はオブジェクトのヒープ領域を即時に解放しなくなります。

IE 11 を例に説明します。ここでは、無作為にクラス「CDivElement」を選択しました。最新の更新プログラム適用前は、このクラスの関数「operator delete」が、オブジェクトのヒープ領域を即時に削除しました。図1 は、最新のセキュリティ更新プログラム適用前のコードです。

図1:最新のセキュリティ更新プログラム適用前のコード
図1:最新のセキュリティ更新プログラム適用前のコード

最新のセキュリティ更新プログラム適用後は、このコードは図2 のように変更されました。

図2:更新プログラム適用後の新コード
図2:更新プログラム適用後の新コード

この新しいコードは、関数「MemoryProtection::CMemoryProtector::ProtectedFree」を呼び出します。この関数は、今回の更新で新しく導入されたものです。この関数で、「CMemoryProtector」を格納する配列にオブジェクトのアドレスと長さが保存されることが分かります。「CMemoryProtector」のインスタンスのアドレスは、「スレッド局所記憶(Thread local storage、TLS)」に記録されます。こうすることで、このオブジェクトのヒープ領域は解放する必要がなくなり、同じスレッド内のコードはその後もオブジェクトのヒープ領域にアクセスできます。

オブジェクトのヒープ領域は、いつ解放されるのでしょうか。これは以下の 2点で起こります。

  1. 「MSHTML!GlobalWndProc」の冒頭で、関数「CMemoryProtector::ProtectCurrentThread」を呼び出します。この関数は、「CMemoryProtector::ReclaimMemoryWithoutProtection」を呼び出し、TLS に保存された配列にあるすべてのアイテムを実際に解放します。
  2. 図3:コールスタックの例
    図3:コールスタックの例

  3. オブジェクトを削除し、「CMemoryProtector::ProtectedFree」を呼び出したとき、待機中の「delay free」のオブジェクトサイズが、合計でしきい値を超えた場合に、解放のプロセスが開始されます。

■「delay free」は、「解放後使用」の脆弱性利用の攻撃をどう軽減できるか
「解放後使用」の脆弱性利用の一般的な攻撃は、オブジェクトのヒープ領域が解放された時に始まります。「delay free」の改善策により、攻撃者は解放されたオブジェクトのヒープ領域を占拠するタイミングを見つけるのが難しくなります。上述したように、その時点のヒープ領域を解放するタイミングは、「MSHTML!GlobalWndProc」にあります。攻撃者が解放されたオブジェクトのヒープ領域を占拠したい場合は、「MSHTML!GlobalWndProc」の後に行う必要があります。この関数は、ウィンドウもしくはアプリケーションで定義したメッセージを受信した時に呼び出されます。攻撃者が JavaScript で関数「alert」を呼び出した場合、IE は「MSHTML!GlobalWndProc」を呼び出します。その後、攻撃者はオブジェクトのヒープ領域を占拠するため、ヒープスプレーのコードを書き込みます。起こりうる攻撃のシナリオについては、「隔離されたヒープ」に関する記事で考察しました。

この攻撃は成功するでしょうか。「MSHTML!GlobalWndProc」の呼び出しによって、オブジェクトのヒープ領域がその都度解放されないため、この攻撃は失敗します。こうした攻撃を避けるために、IE はヒープ領域を解放する前に、現時点のスタックの位置を確認していることがコードから分かります。IE は、JavaScript の実行完了後に、オブジェクトのヒープ領域が解放されるのを確認します。

Google Chrome は、脆弱性利用の攻撃を緩和するためにメモリ保護を行っています。Google Chrome では、ヒープ領域をいくつかのパーティションに分けています。オブジェクトはそれに対応したパーティションに割り当てられます。例えば、文書オブジェクトモデル(DOM)のノードオブジェクトは、特定のパーティションに割り当てられ、配列バッファのオブジェクトは、別のパーティションに割り当てられます。この部分は、「隔離されたヒープ」に相当するものと考えられます。しかし、「delay free」に相当する部分はないように見受けられます。

Adobe Flash Player に存在する「Type Confusion(型の取り違え)」の脆弱性のようなその他の種類の脆弱性は、今回の改善策では対処されていませんが、Microsoft が「解放後使用」の脆弱性利用に対して引き続き取り組んでいることは喜ばしいことです。今回の新しい改善策と「解放されたヒープ」の併用により、「解放後使用」の脆弱性利用の攻撃は、いっそう困難となるでしょう。

参考記事:

 翻訳:品川 暁子(Core Technology Marketing, TrendLabs)