动态链接库安全性

当应用程序动态加载动态链接库而不指定完全限定的路径名称时,Windows 会尝试通过按特定顺序搜索一组定义完善的目录来查找 DLL,如 动态链接库搜索顺序中所述。 如果攻击者控制 DLL 搜索路径上的某个目录,则可以在该目录中放置 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、LoadLibraryExCreateProcessShellExecute 函数时指定完全限定的路径。

  • 将 LOAD_LIBRARY_SEARCH 标志与 LoadLibraryEx 函数一起使用,或将这些标志与 SetDefaultDllDirectories 函数一起使用,以建立进程的 DLL 搜索顺序,然后使用 AddDllDirectorySetDllDirectory 函数修改列表。 有关详细信息,请参阅动态链接库搜索顺序

    Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008: 这些标志和函数在安装了 KB2533623 的系统上可用。

  • 在安装了 KB2533623 的系统上,将 LOAD_LIBRARY_SEARCH 标志与 LoadLibraryEx 函数一起使用,或者将这些标志与 SetDefaultDllDirectories 函数一起使用,为进程建立 DLL 搜索顺序,然后使用 AddDllDirectorySetDllDirectory 函数修改列表。 有关详细信息,请参阅动态链接库搜索顺序

  • 请考虑使用 DLL 重定向清单 ,以确保应用程序使用正确的 DLL。

  • 使用标准搜索顺序时,请确保已启用安全 DLL 搜索模式。 这会将用户的当前目录置于搜索顺序的后面,从而增加了 Windows 在恶意复制之前找到 DLL 的合法副本的可能性。 默认情况下,安全 DLL 搜索模式从 Windows XP 开始启用,Service Pack 2 (SP2) ,并由 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode 注册表值控制。 有关详细信息,请参阅动态链接库搜索顺序

  • 请考虑使用空字符串 (“”) 调用 SetDllDirectory ,从标准搜索路径中删除当前目录。 这应该在进程初始化的早期完成一次,而不是在调用 LoadLibrary 之前和之后完成。 请注意 ,SetDllDirectory 会影响整个进程,并且具有不同值的多个调用 SetDllDirectory 的线程可能会导致未定义的行为。 如果应用程序加载第三方 DLL,请仔细测试以识别任何不兼容情况。

  • 除非启用了安全进程搜索模式,否则不要使用 SearchPath 函数检索 DLL 路径以便进行后续 LoadLibrary 调用。 如果未启用安全进程搜索模式, 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。 此类调用可能表示应用程序中存在漏洞。