Dynamic-Link ライブラリのセキュリティ
アプリケーションが完全修飾パス名を指定せずにダイナミック リンク ライブラリを動的に読み込む場合、「ライブラリ検索順序の 」の説明に従って、適切に定義された一連のディレクトリを特定の順序で検索して DLL の検索Dynamic-Link 試みます。 攻撃者が DLL 検索パス上のディレクトリの 1 つを制御すると、そのディレクトリに DLL の悪意のあるコピーが配置される可能性があります。 これは、DLL プリロード攻撃 または バイナリ植付攻撃と呼ばれることもあります。 システムが侵害されたディレクトリを検索する前に DLL の正当なコピーが見つからない場合は、悪意のある DLL が読み込まれます。 アプリケーションが管理者特権で実行されている場合、攻撃者はローカル特権の昇格に成功する可能性があります。
たとえば、アプリケーションがユーザーの現在のディレクトリから DLL を読み込み、DLL が見つからない場合に正常に失敗するように設計されているものとします。 アプリケーションは、LoadLibrary を DLL の名前だけで呼び出します。これにより、システムは DLL を検索します。 安全な DLL 検索モードが有効になっていて、アプリケーションが代替検索順序を使用していない場合、システムは次の順序でディレクトリを検索します。
- アプリケーションの読み込み元ディレクトリ。
- システム ディレクトリ。
- 16 ビット システム ディレクトリ。
- Windows ディレクトリ。
- 現在のディレクトリ。
- PATH 環境変数に一覧表示されているディレクトリ。
この例を続けると、アプリケーションに関する知識を持つ攻撃者が現在のディレクトリを制御し、そのディレクトリに DLL の悪意のあるコピーを配置します。 アプリケーションが LoadLibrary 呼び出しを発行すると、システムは DLL を検索し、現在のディレクトリ内の DLL の悪意のあるコピーを検索して読み込みます。 その後、DLL の悪意のあるコピーがアプリケーション内で実行され、ユーザーの特権が付与されます。
開発者は、次のガイドラインに従って、DLL プリロード攻撃からアプリケーションを保護できます。
可能な限り、LoadLibrary、LoadLibraryEx、CreateProcess、または ShellExecute関数使用する場合は、完全修飾パスを指定します。
LoadLibraryEx 関数でLOAD_LIBRARY_SEARCHフラグを使用するか、SetDefaultDllDirectories 関数でこれらのフラグを使用してプロセスの DLL 検索順序を確立し、AddDllDirectory または SetDllDirectory関数を使用してリストを変更します。 詳細については、「Dynamic-Link ライブラリの検索順序」を参照してください。
Windows 7、Windows Server 2008 R2、Windows Vista および Windows Server 2008: これらのフラグと機能は、KB2533623 がインストールされているシステムで使用できます。
KB2533623 がインストールされているシステムでは、LoadLibraryEx 関数でLOAD_LIBRARY_SEARCHフラグを使用するか、SetDefaultDllDirectories 関数でこれらのフラグを使用してプロセスの DLL 検索順序を確立し、AddDllDirectory または SetDllDirectory関数使用してリストを変更します。 詳細については、「Dynamic-Link ライブラリの検索順序」を参照してください。
DLL リダイレクト または マニフェスト を使用して、アプリケーションで適切な DLL が使用されるようにすることを検討してください。
標準の検索順序を使用する場合は、安全な DLL 検索モードが有効になっていることを確認します。 これにより、ユーザーの現在のディレクトリが検索順序の後に配置され、Windows が悪意のあるコピーの前に DLL の正当なコピーを見つける可能性が高くなります。 セーフ DLL 検索モードは、Windows XP Service Pack 2 (SP2) 以降では既定で有効になり、HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode レジストリ値によって制御されます。 詳細については、「Dynamic-Link ライブラリの検索順序」を参照してください。
SetDllDirectory を空の文字列 ("") で呼び出して、標準の検索パスから現在のディレクトリを削除することを検討してください。 これは、LoadLibraryの呼び出しの前後ではなく、プロセス初期化の早い段階で行う必要があります。 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 読み込み操作を調べるには
- プロセス モニターを開始します。
- プロセス モニターには、次のフィルターを含めます。
- 操作は CreateFile です
- 操作は LoadImage です
- パスに .cpl が含まれています
- パスに .dll が含まれています
- パスに .drv が含まれています
- パスに .exe が含まれています
- パスに .ocx が含まれています
- パスに .scr が含まれている
- パスに .sys が含まれています
- 次のフィルターを除外します。
- プロセス名が procmon.exe
- プロセス名が Procmon64.exe
- プロセス名はシステムです
- 操作はIRP_MJ_で始まります
- 操作はFASTIO_で始まります
- 結果は SUCCESS です
- パスは pagefile.sys で終わります
- 現在のディレクトリが特定のディレクトリに設定された状態でアプリケーションの起動を試みます。 たとえば、ファイル ハンドラーがアプリケーションに割り当てられている拡張子を持つファイルをダブルクリックします。
- プロセス モニターの出力で、DLL を読み込むための現在のディレクトリへの呼び出しなど、疑わしいパスがないか確認します。 この種の呼び出しは、アプリケーションの脆弱性を示している可能性があります。