ダイナミック リンク ライブラリのセキュリティ

アプリケーションが完全修飾パス名を指定せずにダイナミック リンク ライブラリを動的に読み込む場合、Windows は「ダイナミック リンク ライブラリの検索順序」で説明されているように、明確に定義された一連のディレクトリを特定の順序で検索して DLL の 検索を試みます。 攻撃者が DLL 検索パス上のディレクトリの 1 つを制御すると、そのディレクトリに DLL の悪意のあるコピーが配置される可能性があります。 これは、 DLL プリロード攻撃 または バイナリ植え付け攻撃と呼ばれることもあります。 システムが侵害されたディレクトリを検索する前に DLL の正当なコピーを見つけられない場合は、悪意のある DLL が読み込まれます。 アプリケーションが管理者特権で実行されている場合、攻撃者はローカル特権の昇格に成功する可能性があります。

たとえば、アプリケーションがユーザーの現在のディレクトリから DLL を読み込み、DLL が見つからない場合に正常に失敗するように設計されているものとします。 アプリケーションは、DLL の名前だけで LoadLibrary を呼び出します。これにより、システムは DLL を検索します。 安全な DLL 検索モードが有効で、アプリケーションが代替検索順序を使用していない場合、システムは次の順序でディレクトリを検索します。

  1. アプリケーションの読み込み元のディレクトリ。
  2. システム ディレクトリです。
  3. 16 ビット システム ディレクトリ。
  4. Windows ディレクトリ。
  5. 現在のフォルダー。
  6. PATH 環境変数に一覧表示されているディレクトリ。

この例を続けると、アプリケーションの知識を持つ攻撃者が現在のディレクトリを制御し、そのディレクトリに DLL の悪意のあるコピーを配置します。 アプリケーションが LoadLibrary 呼び出しを発行すると、システムは DLL を検索し、現在のディレクトリ内の DLL の悪意のあるコピーを検索して読み込みます。 その後、DLL の悪意のあるコピーがアプリケーション内で実行され、ユーザーの特権が付与されます。

開発者は、次のガイドラインに従って、DLL プリロード攻撃からアプリケーションを保護するのに役立ちます。

  • LoadLibrary、LoadLibraryExCreateProcess、または ShellExecute 関数を使用する場合は、可能な限り完全修飾パスを指定します。

  • LoadLibraryEx 関数でLOAD_LIBRARY_SEARCH フラグを使用するか、SetDefaultDllDirectories 関数でこれらのフラグを使用してプロセスの DLL 検索順序を確立し、AddDllDirectory 関数または SetDllDirectory 関数を使用してリストを変更します。 詳細については、「ダイナミック リンク ライブラリの検索順序」を参照してください。

    Windows 7、Windows Server 2008 R2、Windows Vista、Windows Server 2008: これらのフラグと機能は、 KB2533623 がインストールされているシステムで使用できます。

  • KB2533623 がインストールされているシステムでは、LoadLibraryEx 関数でLOAD_LIBRARY_SEARCH フラグを使用するか、SetDefaultDllDirectories 関数でこれらのフラグを使用してプロセスの DLL 検索順序を確立し、AddDllDirectory 関数または SetDllDirectory 関数を使用してリストを変更します。 詳細については、「ダイナミック リンク ライブラリの検索順序」を参照してください。

  • アプリケーションで正しい DLL が使用されるように、 DLL リダイレクト または マニフェスト を使用することを検討してください。

  • 標準の検索順序を使用する場合は、安全な DLL 検索モードが有効になっていることを確認します。 これにより、ユーザーの現在のディレクトリが検索順序の後に配置され、Windows が悪意のあるコピーの前に DLL の正当なコピーを見つける可能性が高くなります。 セーフ DLL 検索モードは、Windows XP Service Pack 2 (SP2) 以降では既定で有効になっており、safeDllSearchMode レジストリ値HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\によって制御されます。 詳細については、「ダイナミック リンク ライブラリの検索順序」を参照してください。

  • 空の文字列 ("") で SetDllDirectory を呼び出して、標準の検索パスから現在のディレクトリを削除することを検討してください。 これは、 LoadLibrary の呼び出しの前後ではなく、プロセスの初期化の早い段階で 1 回行う必要があります。 SetDllDirectory はプロセス全体に影響し、値が異なる SetDllDirectory を呼び出す複数のスレッドが未定義の動作を引き起こす可能性があることに注意してください。 アプリケーションがサードパーティの DLL を読み込む場合は、テストを慎重に行って非互換性を特定してください。

  • セーフ プロセス検索モードが有効になっていない限り、 SearchPath 関数を使用して後続の LoadLibrary 呼び出しの DLL へのパスを取得しないでください。 セーフ プロセス検索モードが有効になっていない場合、 SearchPath 関数は LoadLibrary とは異なる検索順序を使用し、最初にユーザーの現在のディレクトリで指定された DLL を検索する可能性があります。 SearchPath 関数のセーフ プロセス検索モードを有効にするには、SetSearchPathMode 関数とBASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODEを使用します。 これにより、現在のディレクトリが SearchPath 検索リストの末尾に移動され、プロセスの有効期間が終了します。 現在のディレクトリは検索パスから削除されないため、システムが現在のディレクトリに到達する前に DLL の正当なコピーを見つけられない場合でも、アプリケーションは脆弱です。 SetDllDirectory と同様に、SetSearchPathMode の呼び出しはプロセスの初期化の早い段階で行う必要があり、プロセス全体に影響します。 アプリケーションがサードパーティの DLL を読み込む場合は、テストを慎重に行って非互換性を特定してください。

  • DLL を検索する LoadLibrary 呼び出しに基づいてオペレーティング システムのバージョンを想定しないでください。 DLL が正当に存在しないが、DLL の悪意のあるコピーが検索パスにある環境でアプリケーションが実行されている場合は、DLL の悪意のあるコピーが読み込まれる可能性があります。 代わりに、「 システム バージョンの取得」で説明されている推奨される手法を使用してください。

プロセス モニター ツールを使用すると、脆弱な可能性がある DLL の読み込み操作を特定できます。 プロセス モニター ツールは から https://technet.microsoft.com/sysinternals/bb896645.aspxダウンロードできます。

次の手順では、プロセス モニターを使用して、アプリケーションでの DLL の読み込み操作を調べる方法について説明します。

プロセス モニターを使用してアプリケーションの DLL 読み込み操作を調べるには

  1. プロセス モニターを開始します。
  2. プロセス モニターに、次のフィルターを含めます。
    • 操作は CreateFile です
    • 操作は LoadImage です
    • パスに.cplが含まれています
    • パスに.dllが含まれています
    • パスに .drv が含まれています
    • パスに.exeが含まれています
    • パスに .ocx が含まれています
    • パスに .scr が含まれています
    • パスに.sysが含まれています
  3. 次のフィルターを除外します。
    • プロセス名がprocmon.exe
    • プロセス名がProcmon64.exe
    • プロセス名はシステムです
    • 操作は IRP_MJ_ で始まります
    • 操作は FASTIO_ で始まります
    • 結果は SUCCESS です
    • パスは pagefile.sys で終わります
  4. 現在のディレクトリを特定のディレクトリに設定して、アプリケーションの起動を試みます。 たとえば、ファイル ハンドラーがアプリケーションに割り当てられている拡張子を持つファイルをダブルクリックします。
  5. プロセス モニターの出力で、DLL を読み込む現在のディレクトリの呼び出しなど、疑わしいパスがないか確認します。 この種の呼び出しは、アプリケーションの脆弱性を示している可能性があります。