Windows Vista Service Pack 1 (SP1) 于 2011 年 7 月 12 日結束。 若要繼續接收適用于 Windows 的安全性更新,請確定您Windows使用 Service Pack 2 (SP2) 。 若要詳細資訊,請參閱此 Microsoft 網頁:部分版本的 microsoft Windows。

當應用程式動態載入動態連結程式庫 (DLL) 而不指定完整路徑時,Windows會嘗試搜尋定義明確的目錄集來尋找 DLL。 如果攻擊者取得其中一個目錄的控制權,他們可能會強制應用程式載入惡意的 DLL 副本,而不是預期中的 DLL。 這些攻擊稱為「DLL 預載入攻擊」,且在所有支援動態載入共用 DLL 文件庫的作業系統中很常見。 這類攻擊的效果可能是,攻擊者可以在執行應用程式的使用者環境中執行程式碼。 當應用程式以系統管理員角色執行時,可能會導致許可權的局部提升。 我們瞭解這些攻擊的重新興趣。 為了限制此問題對共同客戶的影響,我們會將這份檔發佈給開發人員社群,以確保他們瞭解此問題,並擁有必要的工具來解決其應用程式中的問題。

摘要

DLL 預載入攻擊的描述

LoadLibrary 型攻擊

當應用程式在不指定完整路徑的情況下動態載入 DLL 時,Windows會嘗試以線性方式搜尋定義良好的目錄集 ,稱為 DLL 搜尋順序,以找出此 DLL。 如果Windows DLL 搜尋順序中找到 DLL,它會載入該 DLL。 不過,Windows在 DLL 搜尋順序的任何目錄中找不到 DLL,它會將失敗返回 DLL 載入作業。 以下是 LoadLibraryLoadLibraryEx函數的 DLL 搜尋順序,用於動態載入 DLL:

  1. 應用程式進行載入的目錄

  2. 系統目錄

  3. 16 位元系統目錄

  4. Windows 目錄

  5. 目前的工作目錄 (CWD)

  6. PATH 環境變數中所列的目錄



請考慮下列案例:


  • 應用程式載入 DLL 時,不會指定預期在應用程式的 CWD 中尋找的完全合格路徑。

  • 當找不到 DLL 時,應用程式已做好處理該案例的充分準備。

  • 攻擊者知道此應用程式的這項資訊,並控制 CWD。

  • 攻擊者在 CWD 中複製自己特別製作的 DLL 版本。 這假設攻擊者具有執行此操作的許可權。

  • Windows DLL 搜尋順序中的目錄,然後于應用程式的 CWD 中尋找 DLL。

在此情境中,特別製作的 DLL 在應用程式中執行,並取得目前使用者的許可權。

建議 若要防範此攻擊,應用程式可以使用空白字串
("") ,從 DLL 搜尋路徑移除目前的工作目錄
(CWD) 。 如果應用程式需要從目前的目錄載入 DLL,請取得目前的工作目錄,並使用該目錄傳遞 LoadLibrary 的完全合格路徑



我們也發現,有些開發人員會使用 LoadLibrary 來驗證是否有特定的 DLL,以判斷使用者Windows執行哪個版本的 DLL。 您應該注意,這會使應用程式容易受到攻擊。 如果受影響的文件庫確實不存在於應用程式Windows版本上,攻擊者可能會將名稱相同的文件庫引入 CWD。 我們強烈建議您不要使用此技巧。 請改為使用 MSDN 文章 「取得系統版本」中所述的建議技巧。

載入協力廠商外掛程式且無法強制外掛程式在其 LoadLibrary 通話中使用合格路徑的應用程式,應撥打 SetDllDirectory ("") 以移除 CWD,然後打電話給 SetDllDirectory ("外掛程式安裝位置") ,將外掛程式安裝目錄新增到 DLL 搜尋路徑。

SearchPath 型攻擊

當應用程式使用 SearchPath API 尋找 DLL 並動態載入 SearchPath 所返回的路徑時,也發生 類似的攻擊。 以下是 SearchPath API 的預設搜尋順序:

  • 應用程式進行載入的目錄

  • 目前的工作目錄 (CWD)

  • 系統目錄

  • 16 位元系統目錄

  • Windows 目錄

  • PATH 環境變數中所列的目錄

不建議使用此模式,因為它不安全。 如果輸出的預定用途是在 LoadLibrary 函數的通話中,我們不建議使用 SearchPath 函數做為尋找 .dll 檔案的方法。 這可能會導致找到錯誤的.dll,因為 SearchPath 函數的搜尋順序與 LoadLibrary 函數所使用的搜尋順序不同。 如果您必須尋找並載入.dll,請使用 LoadLibrary 函數。

ShellExecute 和 CreateProcess


當開發人員呼叫類似函數 ,例如 ShellExecuteCreateProcess以載入外部可執行檔時,這些問題也會有變化。 我們建議您開發人員在載入二進位檔案時小心,並指定完全合格的路徑。 當您載入二進位而非文件庫時,這應該會降低複雜度。

軟體發展人員的建議步驟

我們建議開發人員執行下列操作:

  • 驗證其應用程式是否載入非安全文件庫 (本文稍後會提供每個範例) 。 這些包括下列專案:

    • 使用 SearchPath 識別文件庫或元件的位置。

    • 使用 LoadLibrary 來識別作業系統版本。

  • 您可以針對 LoadLibrary、CreateProcess 和 ShellExecute 的所有通話使用完全合格的路徑。

  • 使用空白字串 ("") 將呼叫套用至 SetDllDirectory,以從需要的預設 DLL 搜尋順序移除目前的工作目錄。 請注意,SetDllDirectory 會影響整個程式。 因此,您應該在程式初始化的初期執行此一次,而不是在呼叫 LoadLibrary 之前和之後執行。 由於 SetDllDirectory 會影響整個程式,因此使用不同值撥打 SetDllDirectory 的多個執行緒可能會導致未定義的行為。 此外,如果程式是設計用來載入協力廠商 DLL,則需要測試才能判斷進行全程式設定是否會導致不相容。 已知問題是,當應用程式取決於Visual Basic for Applications,全程式設定可能會導致不相容。

  • 使用 SetSearchPathMode函數為程式啟用安全程式搜尋模式。 這會將目前的工作目錄移至 SearchPath 搜尋清單中程式生命週期的最後一個位置。

  • 避免使用 SearchPath 檢查 DLL 是否存在,而不指定完整路徑,即使已啟用安全搜尋模式,因為這仍可能會導致 DLL 預載入攻擊。

識別非安全文件庫載入的指南

在原始程式碼中,以下是非安全文件庫載入的範例:

  • 在下列程式碼範例中,應用程式會使用最schannel.dll搜尋路徑來搜尋「schannel.dll」。 如果攻擊者可以在 CWD 中schannel.dll,應用程式甚至會先載入,Windows目錄尋找適當的文件庫。

    DWORD retval = SearchPath(NULL, "schannel", ".dll", err, result, NULL); 
    HMODULE handle = LoadLibrary(result);
  • 在下列程式碼範例中,應用程式會嘗試從本文開頭所述的各種應用程式和作業系統位置載入文件庫,以用於 LoadLibrary () 通話。 如果檔案不存在有任何風險,應用程式可能會嘗試從目前的工作目錄載入檔案。 此案例比上一個範例稍微不太危險。 不過,如果環境無法完全預測,它仍然會使應用程式使用者暴露在風險中。

    HMODULE handle = LoadLibrary("schannel.dll");




以下是更好、更安全的文件庫載入範例:

  • 在下列程式碼範例中,使用完整路徑直接載入文件庫。 除非攻擊者已經擁有應用程式目標目錄的寫入權限,否則不會引入惡意程式碼。

    HMODULE handle = LoadLibrary("c:\\windows\\system32\\schannel.dll");



    注意 若要瞭解如何判斷系統目錄,請參閱下列資源

    :GetSystemDirectory

    HTTP://msdn.microsoft.com/en-us/library/ms724373%28VS.85%29.aspxSHGetKnownFolderPath

    HTTP://msdn.microsoft.com/en-us/library/bb762188%28v=VS.85%29.aspx

  • 在下列程式碼範例中,在呼叫 LoadLibrary 之前,會先從搜尋路徑移除目前的工作目錄。 這可大幅降低風險,因為攻擊者必須控制應用程式目錄、Windows 目錄,或使用者路徑中指定的任何目錄,才能使用 DLL 預載入攻擊。

    SetDllDirectory ("");
    HMODULE handle = LoadLibrary("schannel.dll");
  • 在已安裝安全性更新 963027 (MS09-014) 所述的所有系統上,下列程式碼會永久將 CWD 移至搜尋順序的最後一個位置。 任何稍後嘗試變更搜尋模式之程式內部對 SetSearchPathMode 函數的通話都會失敗。

    SetDllDirectory ("");
    HMODULE handle = LoadLibrary("schannel.dll");
  • 在下列程式碼範例中,在呼叫 LoadLibrary 之前,會先從搜尋路徑移除目前的工作目錄。 這可大幅降低風險,因為攻擊者必須控制應用程式目錄、Windows 目錄,或使用者路徑中指定的任何目錄,才能使用 DLL 預載入攻擊。

    SetSearchPathMode (BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE | BASE_SEARCH_PATH_PERMANENT );
    HMODULE handle = LoadLibrary("schannel.dll");

使用流程監視器來動態偵測非安全負載

Microsoft 會發佈名為程式監視器的工具。 此工具可讓開發人員和系統管理員密切追蹤執行中的程式列為。 程式監視器可用來動態偵測您的其中一個應用程式是否容易受到這類問題的影響。

  • 若要下載程式監視器,請流覽下列 Microsoft 網頁:

    http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx

  • 嘗試使用 CWD 設定至特定目錄來啟動您的應用程式。 例如,按兩下副檔名的檔案,檔案處理常式會指派給您的應用程式。

  • 使用下列篩選設定流程
    監視器: 替代文字


  • 如果遭到攻擊,會看到類似下列內容: 替代文字對遠端檔案共用進行呼叫以載入 DLL 表示這是容易受到攻擊

    的程式。

其他相關資訊

若要詳細資訊,請流覽下列 Microsoft 網頁:

動態連結文件庫搜尋順序

HTTP://msdn.microsoft.com/en-us/library/ms682586 (VS.85) .aspxSearchPath 函數上的 MSDN 檔

HTTP://msdn.microsoft.com/en-us/library/aa365527 (VS.85) .aspxLoadLibrary 函數上的 MSDN 檔

HTTP://msdn.microsoft.com/en-us/library/ms684175 (VS.85) .aspxSetDllDirectory 函數上的 MSDN 檔

HTTP://msdn.microsoft.com/en-us/library/ms686203 (VS.85) .aspxSetSearchPathMode 函數上的 MSDN 檔

HTTP://msdn.microsoft.com/en-us/library/dd266735 (VS.85) .aspx由 David Leblanc 撰寫的部落格文章,主要安全性工程師與 Microsoft Office

HTTP://blogs.msdn.com/b/david_leblanc/archive/2008/02/20/dll-preloading-attacks.aspxDLL 預載入攻擊的 MSRC 工程小組 Andrew Throths 撰寫的部落格文章

http://blogs.technet.com/b/srd/archive/2009/04/14/ms09-014-addressing-the-safari-carpet-bomb-vulnerability.aspx

其他資源

Need more help?

擴展您的技能

探索訓練 >

優先取得新功能

加入 MICROSOFT 測試人員 >

Was this information helpful?

How satisfied are you with the translation quality?
What affected your experience?

Thank you for your feedback!

×