DLLハイジャックを防ぐ方法

概要

今週は、セキュリティコミュニティから報告されたDLLハイジャック脆弱性のニュースでもちきりでした。発端となったのは、セキュリティ研究者であるParvez Anwar氏がMicrosoft Officeで発見したゼロディDLLハイジャックでした。

そのすぐ後にsecurify.nlのWebサイトで記事が発表され、同様の攻撃に関する詳細と、DLLおよびOLEに潜在的な攻撃対象領域が数多く存在することが解説されました。

ダイナミックリンクライブラリ(DLL)とは、Windowsオペレーティングシステムの基本的なコンポーネントです。Windowsアプリケーションの起動時に、必要に応じてロードされるDLLもあります。DLLには、アプリケーションプログラミングインタフェース(API)やプロシージャといったリソースをソフトウェアアプリケーションに提供するという役割があります。したがって、プログラムがロードするDLLをコントロールできれば、ロードプロセスに悪意のあるDLLを挿入できるわけです。実際、このような手口は以前から悪用されてきました。インターネットでもこの攻撃手法を解説した記事はかなりあり、特にMicrosoftの記事でも取り上げられています。

Microsoft Officeは、DLLコンポーネントがシステムで見つからないとDLLを検索するのですが、今回発見されたMicrosoftゼロディ脆弱性はその検索方法に存在し、これを悪用することによってDLLハイジャックが可能になります。そして以下で説明しているように、このような脆弱性はMicrosoft Officeだけに限定されるものではありません。

攻撃の詳細

DLLの検索順序は、Microsoftが明確に文書化しています。プログラムは、DLLをロードする際、システム構成に応じてディレクトリの検索順序を決定します。次に、デフォルトの検索順序を示します。

  1. アプリケーションのロード元となったディレクトリ
  2. カレントディレクトリ
  3. システムディレクトリ。通常はC:\Windows\System32\(このディレクトリは、GetSystemDirectory関数を呼び出して取得)
  4. 16ビットシステムディレクトリ(このディレクトリパスを取得する専用の関数はありませんが、検索は実行される)
  5. Windowsディレクトリ(GetWindowsDirector関数を呼び出して取得)
  6. PATH環境変数で指定されているディレクトリ

ここで問題になるのは、カレントディレクトリです。プログラムがカレントディレクトリからDLLをロードしようとすると、DLLハイジャックが可能になります。

たとえば、ユーザーがMicrosoft Wordドキュメントを開くと、Microsoft Officeはドキュメントファイルの格納場所からDLLコンポーネントをロードしようとします。つまり、悪意のあるDLLをドキュメントの格納場所に配置しておけば、Microsoft Officeは細工されたコードをロードしてしまいます。

また、細工されたDLLが格納されたWindows共有フォルダを使って、Microsoftのドキュメントファイルを共有するケースも考えられます。

SafeDllSearchModeが有効になっている場合、この手法での攻撃は難しくなります。SafeDllSearchModeを有効にすると、DLLの検索順序は以下のようになります。

  1. lpFileName関数で指定したディレクトリ
  2. システムディレクトリ(GetSystemDirectory関数を呼び出して取得)
  3. 16ビットシステムディレクトリ(このディレクトリパスを取得する専用の関数はありませんが、検索は実行される)
  4. Windowsディレクトリ(GetWindowsDirector関数を呼び出して取得)
  5. カレントディレクトリ
  6. PATH環境変数で指定されているディレクトリApp Pathsレジストリキーでアプリケーションごとに指定したパスは含まれていない点に注意してください。DLL検索パスの計算では、App Pathsキーは考慮されません。

一方で、カレントディレクトリは検索対象に含まれています。デフォルトとの違いは、システムディレクトリでDLLコンポーネントを検索し、見つからなければカレントディレクトリを検索する点です。

DLLハイジャックを防御する方法

次に、DLLハイジャック攻撃を防ぐ方法をいくつかご紹介しましょう。

この攻撃への対策としてエンドユーザーが実行できるのは、ベンダーが提供する最新パッチを適用することです。また、次の手順でシステムのセキュリティを強化することも可能です。

  1. メモ帳を開きます。
  2. 次のテキストをコピーし、貼り付けます。

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession Manager]
"SafeDllSearchMode"=dword:00000001
[HKEY_LOCAL_MACHINESystemCurrentControlSetControlSession Manager]
"CWDIllegalInDllSearch"=dword:ffffffff

  1. システム上に「patch.reg」という名前で保存します。
  2. patch.regをダブルクリックし、Windowsのプロンプトが開いたら[はい]をクリックします。

このスクリプトによってSafeDllSearchModeが有効になります。これで、カレントディレクトリからDLLはロードされなくなります。

開発者の皆様は、Microsoftが推奨する手順を実行してください。

フォーティネットは、学習とデモの目的で小さなツールを作成しました。このツールは、新しく生成されたプロセスを追跡(トラッキング)し、プロセスが見つかるとフックして、空文字列を引数に指定してSetDLLDirectory APIを呼び出します。これにより、この新しいプロセスはカレントディレクトリからDLLをロードしなくなります。ツールのソースコードはこちらから取得できます。

ツールのデモ動画をご覧ください。

-= FortiGuard Lion Team =