Windowsメッセージによる権限上昇の危険性


Cyber Security Management 2004年6月号


本文書は、Cyber Security Management誌に寄稿した記事の原稿を、CSM編集部殿の許可を得た上で掲載したものです。




組織のネットワークセキュリティを確保する上で、コンピュータシステムに対するユーザの権限を限定することは非常に重要である。一般ユーザがコンピュータのシステム管理権限を持つというようなことは、通常は考えられない。しかし、ソフトウェアのセキュリティホールを利用すれば、一般ユーザとしてログオンしながらシステム管理権限を得ることも可能となる場合がある。

今回は、Windowsの基本的な機能であるWindowsメッセージを利用した権限上昇の危険性について、いくつかの例をあげながら解説する。




Windowsアプリケーションと「メッセージ」


WindowsのようなGUI(グラフィカル・ユーザ・インターフェイス)ベースのシステムでは、アプリケーションプログラムは画面上に「ウィンドウ」を表示し、それに対するユーザのマウス操作やキー入力に従って処理を行う。

例えばユーザがマウスを動かしたり、マウスボタンを押したり、あるいはキーボードからキー入力を行った場合、OS(オペレーティング・システム)は行われた操作に該当する「メッセージ」と呼ばれるデータの集合体をアプリケーションのウィンドウへ通知する。それによってアプリケーションは「ユーザからどのような指示があったか」を理解し、適切な処理を行うことができるわけだ(図1)。


図1 マウスをクリックすると、OSがアプリケーションに「マウスクリック」のメッセージを通知する


このようにウインドウシステムでは、OSとアプリケーションとの間でさまざまなメッセージが飛び交っているのだが、このメッセージというものは何もOSからのみ発生するとは限らない。同じデスクトップ上に存在する、あるアプリケーションから、別のアプリケーションのウィンドウに対してメッセージを通知することも可能である。つまり、図2のようにアプリケーションAからアプリケーションBに対し、「マウスがクリックされた」というようなメッセージを送ることができるのである。


図2 アプリケーションAがアプリケーションBに「マウスクリック」のメッセージを通知する


このようなGUIアプリケーション間のメッセージ授受のメカニズムは、Windowsの基本的な仕様であり、通常は特に問題にはならない。なぜなら、一般には図2におけるアプリケーションAもアプリケーションBも、同一のコンピュータ上で同一のユーザによって実行されるものであり、仮にアプリケーションAが不正なメッセージを送出したとしても、ユーザ権限を越えるような行為は行われないからである。

しかし、もしここでアプリケーションBが特権ユーザのプロセスであったらどうだろうか。一般ユーザ権限で動いているアプリケーションAが、特権ユーザのアプリケーションBのウィンドウに対してメッセージを送りつけ、アプリケーションBがそれに従って処理を行ったとすると何が起こるだろうか。まさにこれが今回解説する「Windowsメッセージによる権限上昇の危険性」のコンセプトである。




ユーティリティマネージャの脆弱性


今年の4月に公開された「Microsoft Windowsのセキュリティ修正プログラム(MS04-011)[1]」で修正された脆弱性(セキュリティホール)の一つに、「ユーティリティマネージャの脆弱性」がある。この脆弱性は、システム権限で動作する「ユーティリティマネージャ」に対して一連のWindowsメッセージを送出することにより、システム権限で任意のプログラムを実行させることができるというものだ。Windows 2000においてこの問題が発生する。

マイクロソフトがパッチを提供した直後に、この脆弱性の報告者の一人であるCesar Cerrudo氏が、インターネットのメーリングリスト上で問題を再現させるためのプログラム・ソースコード(UtilManExploit.c)を公開した。ここではこの検証プログラムの内容を基に、本脆弱性を解説してみよう。

  • まず初めにユーティリティマネージャ(utilman.exe)を起動する必要がある。検証プログラムでは、プログラム中からユーティリティマネージャを起動しているが、ユーザ権限によってはこのようにして起動することはできない。その場合は、Windowsキーと「U」キーを同時に押すことでユーティリティマネージャを起動することができる。図3にユーティリティマネージャのウィンドウを示す。このユーティリティマネージャは、実はWindowsのサービスとして稼動しており、システム権限で動作する。


    図3 ユーティリティマネージャのウィンドウ。これはシステム権限で実行される


  • 次にユーティリティマネージャ・ウィンドウに対して、「コンテキストヘルプ」を表示させるWindowsメッセージを送信する。コンテキストヘルプとは、ウィンドウ上で選択されている項目に関するヘルプメッセージを、ポップアップ形式で表示するものであり、通常は「F1」キーを押すことで表示させることができる。このコンテキストヘルプが表示される際にwinhlp32.exeというプログラムが起動するのだが、ユーティリティマネージャからコンテキストヘルプが起動した場合、utilman.exeと同様にwinhlp32.exeもシステム権限で動作することになる(図4)。


    図4 コンテキストヘルプがポップアップ。この時点でwinhlp32.exeがシステム権限で起動


  • 続けて、コンテキストヘルプに対し「ファイルを開く」ダイアログを表示させるようなメッセージを送信する。すると図5のようなウィンドウが表示される。これはオープンするヘルプファイルを選択するためのウィンドウである。


    図5 「ファイルを開く」ダイアログ・ウィンドウ。通常はここでオープンするヘルプファイルを指定する


  • さらにこのダイアログ・ウィンドウに対して、システムディレクトリ中に存在する「cmd.exe(コマンドプロンプト)」を選択し、コンテキストメニュー(右クリックでポップアップするメニュー)を表示させ、そのメニューから「開く」を選択するようなメッセージを送る(図6)。


    図6 cmd.exeを選択してコンテキストメニューを表示、さらにメニューから「開く」を選択


  • するとcmd.exeが起動し、コマンドプロンプトのウィンドウが開く(図7)。前述のとおりコンテキストヘルプ(つまりwinhlp32.exe)はシステム権限で実行しているため、そこから起動したコマンドプロンプト・ウィンドウもシステム権限で動作することとなる。


    図7 cmd.exeが起動してコマンドプロンプトが開いたところ。システム権限で実行している


このようにユーティリティマネージャの脆弱性を用いることで、一般ユーザ権限でログオンしている場合でも、システム権限のコマンドプロンプトを開くことが可能になる。ここで示した攻撃のように、ある特定の権限のユーザがセキュリティホールを利用してより高い権限を獲得する行為を「権限上昇」と呼ぶ。

一般的に今回のような問題は、GUIを通してユーザと接するような対話型プロセスが、システム権限等の高い権限で実行している場合に、低い権限で動作しているプロセスからの不正なWindowsメッセージを受け付けることにより発生する。今回のケースでは、ユーティリティマネージャ(utilman.exe)という対話型プロセスが、まさにシステム権限で実行していたために発生したと言えよう。

ちなみにマイクロソフトはこの問題に対し、ユーティリティマネージャのウィンドウからコンテキストヘルプの機能を削除することで修正している。




WM_TIMERメッセージを利用したShatter Attack


さて同様にWindowsメッセージを利用した権限上昇の方法として、「Shatter Attack」という攻撃手法がある。Shatter Attackのコンセプトおよび検証ツールは、2002年にChris Paget氏(「Foon」の名で知られている)によって公開された[2]。

先ほど説明したユーティリティマネージャの脆弱性は、システム権限で動作するプロセスに対して通常行うことのできないGUI操作を、Windowsメッセージを送りつけることにより実行させるというものであった。一方Shatter Attackでは、高権限のプロセスに不正なWindowsメッセージを送信する点に変わりはないものの、不正なプログラムコード(いわゆるシェル・コード)をメッセージとして送り込み、メッセージの機能を利用して送り込んだプログラムコードにプロセスの制御を移すといった行為を行う。

Chris Paget氏が最初に指摘したShatter Attackの手法は、「WM_TIMER」というWindowsメッセージを利用したものである。

WM_TIMERメッセージは通常、タイマーの期限が切れた際にプロセスに対して特定の処理を実行させるような目的で使用される。しかしプロセス側でタイマーの設定をしていようがいまいが、プロセスはWM_TIMERメッセージを盲目的に受け取り、そのWM_TIMERメッセージに含まれる関数のアドレスに制御を移すことで指定された処理を実行してしまう。ここにこの脆弱性が存在する。

以下「WinVNC」というソフトウェアを例に取り上げ、WM_TIMERメッセージを用いたShatter Attackについて解説しよう。図8は、WinVNC(バージョン3.3.7)のプロパティ画面を表している。WinVNCは「VNC(Virtual Network Computing)」と呼ばれるコンピュータ遠隔操作ソフトウェアのWindows版であるが、設定によりシステム権限でサービスとして動作するため、Shatter Attackの実例としては都合が良い。


図8 WinVNCのプロパティ画面。赤線で囲った部分がエディットコントロール


図8の中に赤線で示した部分はWinVNCのパスワードを入れるエリアで、「エディットコントロール」と呼ばれるウィンドウ構成部品である。このエディットコントロールに対し、Shatter Attackを実行する。

  • Chris Paget氏が公開しているShatter Attack検証ツール「shatter.exe」を起動する。

  • 「Enumerate windows」あるいは「Get cursor window」により、WinVNCのエディットコントロールのハンドルを取得する(図9。この場合は「12010c」という16進数の値がそれに該当する)。


    図9 shatter.exeのウィンドウ。「Enumerate windows」によりハンドルを取得


  • 「EM_SETLIMITTEXT」メッセージにより、エディットコントロールのテキスト領域の長さ制限を、シェル・コードが入る十分な大きさに拡張する(図10。ここでは16進数でFFFF、つまり65535バイトに拡張している)。


    図10 「EM_SETLIMITTEXT」により、エディットコントロールのテキスト長を拡張


  • 同じく公開されているシェル・コード「sploit.bin」の内容を、ヘキサエディタ等を用いてクリップボードにコピーする。

  • 「WM_PASTE」メッセージにより、先ほどコピーしたクリップボードの内容(つまりシェル・コード)を、WinVNCのエディットコントロールにペーストする(図11。この時点でWinVNCのメモリ中にシェル・コードがコピーされる)。


    図11 「WM_PASTE」により、クリップボード内のシェル・コードをエディットコントロールにペースト


  • 「WM_TIMER」メッセージにより、WinVNCのメモリ中にあるシェル・コードのアドレスへプログラムの制御を移し、シェル・コードを実行させる(図12。ここではアドレスとして16進数で158200を指定しているが、このアドレスの値は事前にデバッガで調べておく必要がある)。


    図12 「WM_TIMER」により、シェル・コードのアドレスにプログラムの制御を移す


  • ここで用いたsploit.binというシェル・コードは、ローカルコンピュータ上の特定のTCPポートに対してコマンドプロンプトを開くものである。そのため、事前に該当するTCPポートで待ち受けておくことにより、システム権限のコマンドプロンプトにアクセスすることができるようになる(図13)。


    図13 ncというプログラムでTCP/123で待ち受け、システム権限のコマンドプロンプトを取得したところ


以上がWM_TIMERメッセージを用いたShatter Attackの概要である。なお、マイクロソフトはこの問題が公開された後に、修正プログラムによってWM_TIMERの仕様を変更した[3]。そのため最新のWindows環境は、WM_TIMERメッセージを利用したShatter Attackによりセキュリティ侵害を受けることはない。




さまざまなShatter Attack手法とその対策


しかしWM_TIMERメッセージが修正されたからといって、Shatter Attackの脅威が存在しなくなったわけではなく、その後、さまざまなShatter Attack手法が研究されている。

2003年7月にOliver Lavery氏が「Win32 Message Vulnerabilities Redux」をいう技術文書を公開した[4]。ここでは「EM_SETWORDBREAKPROC」というWindowsメッセージを使用したShatter Attackの方法が解説されており、実証のためのプログラム・ソースコードも添付されている。

EM_SETWORDBREAKPROCメッセージは通常、エディットコントロールのデフォルトのワードラップ機能を、アプリケーションが用意した別の機能に置き換えるために用いられる。しかしこのメッセージもWM_TIMERと同様に、不正に使用することでプロセスの制御を送り込んだシェル・コードに移すことが可能である。図14はEM_SETWORDBREAKPROCメッセージを使用して、WinVNCに対してShatter Attackを実行した例を示している。


図14 EM_SETWORDBREAKPROCメッセージを利用したShatter Attackプログラムの実行例


また2003年10月には、各種のWindowsメッセージ(HDM_GETITEMRECT、PBM_GETRANGE、...)を利用したShatter Attackの手法を、サンプル・プログラムを使って解説した「Shattering By Example」という文書が、Brett Moore氏によって公開された[5]。ここではWindowsメッセージを用いて特定のメモリ・アドレスに、任意のデータを書き込み、例外処理を起こさせることで不正なコードを起動する、さまざまな方法が紹介されている。

先に解説したユーティリティマネージャの脆弱性や、ここで述べた数々のShatter Attackによる権限上昇は、前述のとおり同一のデスクトップ上で権限の高い対話型プロセスが存在し、権限の低いプロセスから送られる不正なWindowsメッセージを受け付けて処理してしまうことにその根本的な原因がある。

マイクロソフトはこのようなWindowsメッセージを利用した権限上昇の問題について、メッセージ処理の方法を一部変更する等の修正を行ってきているものの、基本的に同一デスクトップ上の対話型プロセスは実行権限にかかわらず同等であり、互いにメッセージを交換できるのは仕様であるという考えを示している[6]。つまり、Shatter Attackを防ぐためには、OS側ではなくアプリケーション開発側、あるいはその利用者側で注意しなければならないわけだ。

どのようなWindowsメッセージによって、どのようなセキュリティ侵害が発生するかは、アプリケーションの機能や構成するコントロール(部品)に依存するが、マイクロソフトのアプリケーションに限らず、GUIを持ち、システム権限で動作するようなものならば、潜在的にWindowsメッセージによる権限上昇攻撃の対象となり得る。例えばそのアプリケーションがコンテキストヘルプ機能を持っていれば、おそらく一つ目の例「ユーティリティマネージャの脆弱性」と同じような攻撃が可能となる。

システム権限で動作する対話型のプロセス(サービス)としては、アンチウィルス・ソフトウェア、パーソナル・ファイアウォール、リモート・デスクトップ製品など、さまざまなものが考えられる。システム管理者は一般ユーザが利用するコンピュータ上でこのようなソフトウェアを使用する場合、Shatter Attack等Windowsメッセージを用いた権限上昇の可能性がないかどうかを十分検討する必要があるだろう。またソフトウェア開発者には、このような攻撃手法の存在を認識し、対話型プロセスを不必要に高い権限で実行させない等の対策を、ソフトウェアの設計・開発段階で講じることが求められる。



[1]  Microsoft Windowsのセキュリティ修正プログラム(MS04-011)
     http://www.microsoft.com/japan/technet/security/bulletin/MS04-011.asp

[2]  Shatter Attacks - How to break Windows
     http://security.tombom.co.uk/shatter.html

[3]  Windows WM_TIMERメッセージ処理の問題により、権限が昇格する(MS02-071)
     http://www.microsoft.com/japan/technet/security/bulletin/ms02-071.asp

[4]  Win32 Message Vulnerabilities Redux
     http://www.idefense.com/application/poi/researchreports/display

[5]  Shattering By Example
     http://www.security-assessment.com/Papers/Shattering_By_Example-V1_03102003.pdf

[6]  報告されたWindowsの構造上の問題に関する情報
     http://www.microsoft.com/japan/technet/security/topics/htshat.asp


2004年4月執筆
塩月 誠人
ネットワークセキュリティコンサルタント