Dynamic-Link 库安全性

当应用程序在不指定完全限定的路径名称的情况下动态加载动态链接库时,Windows 会尝试按特定顺序搜索定义完善的目录集来查找 DLL,如 Dynamic-Link 库搜索顺序中所述。 如果攻击者在 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 预加载攻击:

  • 如果可能,请在使用 LoadLibraryLoadLibraryExCreateProcessShellExecute 函数时指定完全限定的路径。

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

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

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

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

  • 使用标准搜索顺序时,请确保已启用安全的 DLL 搜索模式。 这会在搜索顺序中稍后将用户的当前目录置于此位置,这增加了 Windows 在恶意副本之前找到 DLL 合法副本的可能性。 默认情况下,从 Service Pack 2(SP2)的 Windows XP 开始启用安全 DLL 搜索模式,并由 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 加载作

  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。 此类调用可能表示应用程序中存在漏洞。