动态链接库安全性
当应用程序动态加载动态链接库而不指定完全限定的路径名称时,Windows 会尝试通过按特定顺序搜索一组定义完善的目录来查找 DLL,如 动态链接库搜索顺序中所述。 如果攻击者控制 DLL 搜索路径上的某个目录,则可以在该目录中放置 DLL 的恶意副本。 这有时称为 DLL 预加载攻击 或 二进制植入攻击。 如果系统在搜索受入侵的目录之前找不到 DLL 的合法副本,则会加载恶意 DLL。 如果应用程序以管理员权限运行,则攻击者可能会在本地特权提升中成功。
例如,假设应用程序旨在从用户的当前目录加载 DLL,如果找不到 DLL,则正常失败。 应用程序仅使用 DLL 的名称调用 LoadLibrary ,这会导致系统搜索 DLL。 假设启用了安全 DLL 搜索模式,并且应用程序未使用备用搜索顺序,则系统按以下顺序搜索目录:
- 从中加载应用程序的目录。
- 系统目录。
- 16 位系统目录。
- Windows 目录。
- 当前目录。
- PATH 环境变量中列出的目录。
继续本示例,了解应用程序的攻击者获取当前目录的控制,并将 DLL 的恶意副本置于该目录中。 当应用程序发出 LoadLibrary 调用时,系统会搜索 DLL,在当前目录中查找 DLL 的恶意副本,然后加载它。 然后,DLL 的恶意副本在应用程序中运行,并获取用户的权限。
开发人员可以遵循以下准则,帮助保护其应用程序免受 DLL 预加载攻击:
尽可能在使用 LoadLibrary、LoadLibraryEx、CreateProcess 或 ShellExecute 函数时指定完全限定的路径。
将 LOAD_LIBRARY_SEARCH 标志与 LoadLibraryEx 函数一起使用,或将这些标志与 SetDefaultDllDirectories 函数一起使用,以建立进程的 DLL 搜索顺序,然后使用 AddDllDirectory 或 SetDllDirectory 函数修改列表。 有关详细信息,请参阅动态链接库搜索顺序。
Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008: 这些标志和函数在安装了 KB2533623 的系统上可用。
在安装了 KB2533623 的系统上,将 LOAD_LIBRARY_SEARCH 标志与 LoadLibraryEx 函数一起使用,或者将这些标志与 SetDefaultDllDirectories 函数一起使用,为进程建立 DLL 搜索顺序,然后使用 AddDllDirectory 或 SetDllDirectory 函数修改列表。 有关详细信息,请参阅动态链接库搜索顺序。
使用标准搜索顺序时,请确保已启用安全 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 加载操作
- 启动进程监视器。
- 在进程监视器中,包括以下筛选器:
- 操作为 CreateFile
- 操作为 LoadImage
- 路径包含.cpl
- 路径包含.dll
- 路径包含 .drv
- 路径包含.exe
- 路径包含 .ocx
- 路径包含 .scr
- 路径包含.sys
- 排除以下筛选器:
- 进程名称procmon.exe
- 进程名称Procmon64.exe
- 进程名称为系统
- 操作从IRP_MJ_开始
- 操作从FASTIO_开始
- 结果为 SUCCESS
- 路径以pagefile.sys结尾
- 尝试将当前目录设置为特定目录来启动应用程序。 例如,双击扩展名为应用程序分配的文件处理程序的文件。
- 检查进程监视器输出中是否存在可疑的路径,例如调用当前目录以加载 DLL。 此类调用可能表示应用程序中存在漏洞。