使用 Microsoft 登录
登录或创建帐户。
你好,
使用其他帐户。
你有多个帐户
选择要登录的帐户。

对 Vista Windows Service Pack 1 (SP1) 的支持将于 2011 年 7 月 12 日结束。 若要继续接收 Windows 的安全更新,请确保使用 Service Pack 2 Windows SP2 (Vista) 。 有关详细信息,请参阅此 Microsoft 网页:支持将终止某些版本的Windows。

当应用程序动态加载动态链接库 (DLL) 而不指定完全限定的路径时,Windows尝试通过搜索一组明确定义的目录来查找 DLL。 如果攻击者获取了其中一个目录的控制权,他们可以强制应用程序加载 DLL 的恶意副本,而不是它期望的 DLL。 这些攻击称为"DLL 预加载攻击",对于支持动态加载共享 DLL 库的所有操作系统很常见。 此类攻击的影响可能是攻击者可以在运行应用程序的用户的上下文中执行代码。 以管理员角色运行应用程序时,这可能会导致本地提升权限。 我们知道对此类攻击重新感兴趣。 为了限制此问题对共同客户的影响,我们将本文档发布给开发人员社区,以确保他们了解此问题,并拥有解决其应用程序中的问题的必要工具。

摘要

DLL 预加载攻击的说明

基于 LoadLibrary 的攻击

当应用程序动态加载 DLL 而不指定完全限定的路径时,Windows尝试通过线性搜索一组明确定义的目录(称为 DLL 搜索顺序)找到此 DLL。 如果Windows DLL 搜索顺序中查找 DLL,它将加载该 DLL。 但是,Windows DLL 搜索顺序的任何目录中找不到 DLL,则 DLL 加载操作会失败。 下面是用于动态加载 DLL 的 LoadLibraryLoadLibraryEx函数的 DLL 搜索顺序:

  1. 从其中加载应用程序的目录

  2. 系统目录

  3. 16 位系统目录

  4. Windows 目录

  5. CWD (当前)

  6. PATH 环境变量中列出的目录



请考虑以下方案:


  • 应用程序加载 DLL,而不指定预期在应用程序的 CWD 中查找的完全限定路径。

  • 应用程序完全准备好在找不到 DLL 时处理这种情况。

  • 攻击者知道有关应用程序的此信息并控制 CWD。

  • 攻击者在 CWD 中复制其自己的专门设计的 DLL 版本。 这假定攻击者有权这样做。

  • Windows DLL 搜索顺序中的目录,在应用程序的 CWD 中查找 DLL。

在此方案中,专门设计的 DLL 在应用程序中运行,并获取当前用户的权限。

建议 为了防止此攻击,应用程序可以通过使用空字符串 ("") 调用
SetDllDirectory API,从 DLL 搜索路径中删除当前工作目录
(C) WD ) 。 如果应用程序依赖于从当前目录加载 DLL,请获取当前工作目录,并使用该目录来传递 LoadLibrary的完全限定路径。



我们还注意到,某些开发人员使用 LoadLibrary 来验证特定 DLL 是否存在,以确定用户Windows哪个版本。 应注意,这会使应用程序易受攻击。 如果在应用程序执行Windows上确实不存在受影响的库,攻击者可能会将同名的库引入 CWD 中。 我们强烈建议不要使用此技术。 请改为使用 MSDN 文章"获取系统版本"中所述的建议技术。

加载第三方插件且无法强制插件使用其 LoadLibrary 调用的限定路径的应用程序应调用 SetDllDirectory (""") 以删除 CWD,然后调用 SetDllDirectory ("plugin install location") 以将插件安装目录添加到 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 和 Shell 执行的所有调用使用完全限定的路径(如果可以)。

  • 使用空字符串 ("") 实现对 SetDllDirectory 的调用,以从所需的默认 DLL 搜索顺序中删除当前工作目录。 请注意,SetDllDirectory 会影响整个过程。 因此,应在进程初始化早期执行一次此操作,而不是在调用 LoadLibrary 之前和之后这样做。 由于 SetDllDirectory 会影响整个过程,因此调用 SetDllDirectory 且值不同的多个线程可能会导致未定义的行为。 此外,如果该过程旨在加载第三方 DLL,则测试需要确定进行进程范围的设置是否会导致不兼容性。 一个已知问题是,当应用程序依赖于Visual Basic for Applications时,进程范围的设置可能会导致不兼容。

  • 使用 SetSearchPathMode函数为进程启用安全进程搜索模式。 这会将当前工作目录移到 SearchPath 搜索列表中的最后一个位置,作为进程的生存期。

  • 避免使用 SearchPath 检查 DLL 是否存在,而不指定完全限定的路径,即使启用了安全搜索模式,因为这仍可能导致 DLL 预加载攻击。

有关识别非安全库加载的指南

在源代码中,下面是非安全库加载的示例:

  • 在下面的代码示例中,应用程序使用最schannel.dll搜索路径搜索"schannel.dll"。 如果攻击者可以将schannel.dll CWD 中,则甚至在应用程序搜索相应库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");
  • MS09-014) 中所述安装安全更新 963027 (的所有系统上,以下代码将 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) .aspx有关 SearchPath 函数的 MSDN 文档

http://msdn.microsoft.com/en-us/library/aa365527 (VS.85) .aspx有关 LoadLibrary 函数的 MSDN 文档

http://msdn.microsoft.com/en-us/library/ms684175 (VS.85) .aspx有关 SetDllDirectory 函数的 MSDN 文档

http://msdn.microsoft.com/en-us/library/ms686203 (VS.85) .aspx有关 SetSearchPathMode 函数的 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.aspx有关 DLL 预加载攻击的 MSRC 工程团队 Andrew 一文

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

其他资源

需要更多帮助?

需要更多选项?

了解订阅权益、浏览培训课程、了解如何保护设备等。

社区可帮助你提出和回答问题、提供反馈,并听取经验丰富专家的意见。

此信息是否有帮助?

你对语言质量的满意程度如何?
哪些因素影响了你的体验?
按“提交”即表示你的反馈将用于改进 Microsoft 产品和服务。 你的 IT 管理员将能够收集此数据。 隐私声明。

谢谢您的反馈!

×