トレンドマイクロが運営する脆弱性発見・研究コミュニティ「Zero Day Initiative(ZDI)」は、2018 年 7 月 11 日、Internet Explorer(IE)の危険度の高い脆弱性が実際の攻撃で利用されていることを確認しました。これは、Microsoft の 7 月の月例セキュリティ更新プログラム公開のちょうど翌日のことでした。ZDI は、脆弱性の修正を支援するためにすぐに詳細情報を Microsoft に通知しました。問題の脆弱性には「CVE-2018-8373」という識別番号が割り当てられ、8 月の月例セキュリティ更新プログラムにて修正されています。CVE-2018-8373 は、IE でメモリ内のオブジェクトを処理する VBScript エンジンにおける脆弱性です。影響を受ける IE のバージョンは、IE9、IE10、および IE11 です。ただし、Windows 10 Redstone 3(RS3) の IE11 は、初期設定で VBScript が無効化されているため影響を受けません。影響を受けるバージョンの詳細はこちらを参照してください。
ZDI は、CVE-2018-8373 を利用した不正な Web トラフィックを確認しました。図 1 は問題の URL です。
図 1:CVE-2018-8373 を利用する不正な Web サイトの URL
この脆弱性攻撃では、マルウェアに特徴的な挙動(ヒューリスティック)が確認されています。これにより、より詳細な解析が可能となりました。興味深いことに、VBScript エンジンにおける「遠隔でのコード実行(Remote Code Execution、RCE)」脆弱性「CVE-2018-8174」を利用した攻撃と同一の難読化手法が今回の攻撃で確認されました。CVE-2018-8174 に対処する更新プログラムは2018 年 5 月に公開されています。
図 2:「CVE-2018-8373」および「CVE-2018-8174」を利用する VBScript
さらに図 3 は、各脆弱性を利用してシェルコードを実行する攻撃手法です。
図 3:「CVE-2018-8373」および「CVE-2018-8174」を利用してシェルコードを実行する VBScript
ZDI は、今回確認された CVE-2018-8373 を利用する検体が、CVE-2018-8174 を利用する攻撃と同一の作成者によるものと推測しています。
■脆弱性の原因
では、CVE-2018-8373 の詳細について見ていきましょう。この脆弱性は、VBScript エンジン ”vbscript.dll” で新しく確認された「Use-After-Free(メモリ解放後使用、UAF)」の脆弱性です。実際に確認された攻撃コードには高度な難読化が施されているため、ここでは概念実証(Proof of Concept、PoC)を使って解説します。
図 4:IE の脆弱性「CVE-2018-8373」を利用する概念実証コード
この PoC は、「array」というメンバ変数と、「Class_Initialize」および「Default Property Get P」というメンバ関数が定義された「MyClass」という名前のクラスを定義しています。「Class_Initialize」プロシージャを直接呼び出すのは非推奨のため、オブジェクトをインスタンス化する際は「New」プロシージャを使用します。「Class_Initialize」プロシージャはオブジェクトが初めてインスタンス化される際に自動的に呼び出されます。この PoC では、「Class_Initialize」プロシージャはオーバーロードされており、「VBScriptClass::InitializeClass」関数が呼び出されると、オーバーロードされた関数に処理が移ります。
デフォルトプロパティは、プロパティ名を指定せずにクラス名だけでアクセスすることが可能です。この PoC では、「Default Property Get P」プロシージャは、「MyClass」のデフォルトプロパティをオーバーロードしています。「MyClass」のインスタンス「cls」が呼び出されると、オーバーロードされたプロシージャに処理が移ります。
CVE-2018-8373 を利用して不具合を引き起こす流れは、簡単に以下の 3 段階に分かれています。
- クラスのインスタンス化:「Set cls = New MyClass」
このコードは、オーバーロードされたプロシージャ「Class_Initialize」を呼び出します。「Class_Initialize」内の「ReDim array(2)」は、要素を 3 つ持つ配列を生成するために「vbscript!RedimPreserveArray」関数を呼び出します。
図 5:「ReDim array(2)」実行時のメモリ - 配列要素のアドレスを取得:「cls.array(2)」
このコードは、配列要素のアドレスを取得するために「vbscript!AccessArray」関数を呼び出します。「vbscript!AccessArray」関数は、初めに配列要素のインデックスが有効範囲内にあることを確認します。
図 6:「vbscript!AccessArray」関数は配列要素のインデックスを確認次に、指定された配列要素のアドレスを計算してスタックに格納し、戻り値として返します。
図 7:指定された配列要素のアドレスをスタックに格納 - 配列に要素を格納:「cls.array(2)=cls」
このコードは、「vbscript!AssignVar」関数を呼び出し、「MyClass」のデフォルトプロパティの値を「cls.array(2)」に格納します。デフォルトプロパティを取得する際、「Public Default Property Get P」プロシージャが呼び出され、プロシージャ内の「ReDim array(1)」が実行されます。これにより、元の配列の既存データ「pvData」が解放されます。
図 8:元の配列の既存データ「pvData」が解放されるしかし、「array(2)」のアドレスは、上述した 2 段階目の状態のままスタックに格納されています。そのため、「Public Default Property Get P」プロシージャの戻り値が解放されたメモリ領域にアクセスし、結果として「vbscript!AssignVar」関数でメモリの解放後使用が発生します。
図 9:「vbscript!AssignVar」関数が解放されたメモリを使用上述したように、「vbscript!AccessArray」関数は、配列要素のインデックスが有効範囲内にあることを確認します。しかし、「vbscript!AssignVar」関数によって配列の要素に値を代入する際に、再度インデックスの範囲を確認することはありません。そのため、インデックスの範囲を確認した後で、クラスのデフォルトプロパティの値を取得する「Default Property Get P」プロシージャが配列の長さを変更すると、解放されたメモリ領域へのアクセスが発生してしまいます。これが、CVE-2018-8373 の原因です。
■脆弱性攻撃の手順
CVE-2018-8373 を利用する攻撃は、簡単に以下の 3 段階で実行されます。
- 脆弱性を利用し、2 次元配列の長さを 0x0FFFFFFF に変更
- メモリへの書き込み/メモリからの読み取りを行うプリミティブ関数の実行
- メモリのコンテキスト構造を細工し、シェルコードを実行
- 2 次元配列の長さを変更
初めに、2 つの配列を定義します。ここでは「array1」と「array2」とします。「array1」は上述した PoC の配列で、「array2」は各要素の値が「3」の 2 次元配列です。
図 10:「array2」の定義次に、元の「array1.pvData」を解放し、新しく「array2」を代入するために、「Default Property Get P」プロシージャを呼び出します。元の「array1.pvData」のメモリ上のサイズは、「array2.SAFEARRAY」構造体と同じ 0x30 バイトであるため、「array2.SAFEARRAY」構造体のいくつかは、元の「array1.pvData」の解放されたメモリを再利用します。一方、「Default Property Get P」プロシージャの戻り値 0x0FFFFFFFF を「array2.SAFEARRAY」の「SAFEARRAYBOUND」構造体に設定し、「array2」の長さを 0x0FFFFFFF に変更します。
図 11:「Default Property Get」プロシージャの定義
図 12:配列の長さを変更する手順 - メモリへの書き込み/メモリからの読み取りを行うプリミティブ関数の実行
手順 1 により、UAF を利用することで長さを変更した配列「array1(index_vuln)(0x0FFFFFFE, 2)」が得られます。図 13 のスクリプトにより、「array1」の要素の中から「index_vuln」を検索することが可能です。
図 13:「array1(index_vuln)(0x0FFFFFFE, 2)」を検索するスクリプト次に、「array1(index_vuln)(0x0FFFFFFE, 2)」を利用して、これは「アウト・オブ・バウンド(OOB)」を引き起こし、「type confusion(型の取り違え)」を発生させる要素を 2 つの配列中から検索します。
図 14 および 15:2 つの配列の要素を検索図 14 および 15 により、2 つの配列の要素「array1(index_B)(0, 0)」と「array1(index_vuln)(index_A, 0)」を取得します。これら 2 つの要素はメモリ上で 8 バイトの距離に位置しています。メモリ内を検索する手順は図 16 の通りです。
図 16:メモリ内を検索する手順最後に、2 つの配列の要素を使用し、型の取り違えによってメモリへの書き込み/メモリからの読み取りを行うプリミティブ関数を実行します。
図 17:メモリへの書き込み/メモリからの読み取りを行うプリミティブ関数 - メモリのコンテキスト構造を細工し、シェルコードを実行
メモリからの読み取りを行うプリミティブ関数によって、モジュールのアドレスを漏えいします。
図 18:モジュールのアドレスを漏えいいくつかの VARIANT 型変数について、VarType を 0x4d に、値を 0 に変更することにより、「vbscript!VAR::Clear」関数を呼び出します。これにより、コールスタックのリターンアドレスが「NtContinue」のアドレスに変更され、細工したコンテキスト構造でシェルコードが実行されます。
図 19:VARIANT 型変数の型と値を変更
図 20:シェルコードの実行
トレンドマイクロの解析では、安定してこの脆弱性攻撃を成功させることができました。本記事で解説した CVE-2018-8373 は、CVE-2018-8174 に続き、2018 年に入ってから VBScript エンジンで確認された 2 件目の脆弱性です。将来、VBScript エンジンにおいて別の脆弱性が確認されることも十分予想されます。
■トレンドマイクロの対策
脆弱性対策の第一段階として、利用可能になり次第最新の更新プログラムを適用してください。脆弱性に対処するセキュリティ対策製品の導入も有効です。
ゲートウェイやエンドポイントから、ネットワークそしてサーバにいたる多層的で積極的なセキュリティ対策が、脆弱性を狙う脅威に対抗する鍵となります。トレンドマイクロの法人向けエンドポイント製品「ウイルスバスター™ コーポレートエディション XG」や中小企業向けのクラウド型エンドポイントセキュリティサービス「ウイルスバスター™ ビジネスセキュリティ」は、不正なファイルを検出し、関連する不正な URL をブロックすることによって、強固な保護を提供します。
トレンドマイクロのネットワーク挙動監視ソリューション「Deep Discovery™」は、今日の気づけない標的型攻撃や巧妙化する脅威をリアルタイムで検出および分析し、対処します。専用のエンジンとカスタムサンドボックス機能を使用し、攻撃のライフサイクル全体で相関分析を行い、エンジンやパターンの更新無しで攻撃を検知します。
総合サーバセキュリティ製品「Trend Micro Deep Security™」をご利用のお客様は、以下の DPIルールによってこの脆弱性を利用する脅威から保護されています。
- 1009218 – Microsoft Windows VBScript Engine Use-After-Free Vulnerability
ネットワーク脅威防御ソリューション「TippingPoint」では、以下のMainlineDV filterにより今回の脅威をブロックします。
- 32721: Microsoft VBScript Engine Sub Default Property Use-After-Free Vulnerability
■侵入の痕跡(Indicator of Compromise、IoC)
関連するSHA256値は以下の通りです。
- HTML_EXPLOIT.YYRV:0d6fe137790e2ebdf4fac2dd500656f3a6f74c0d1598251929ea3558f965675f
参考記事:
- 「Use-after-free (UAF) Vulnerability CVE-2018-8373 in VBScript Engine Affects Internet Explorer to Run Shellcode」
by Elliot Cao (Trend Micro Security Research) with Trend Micro’s Zero Day Initiative (ZDI)
翻訳: 澤山 高士(Core Technology Marketing, TrendLabs)