产品: Windows 10 1909、Windows Server 2019(2004及更早版本也受影响但未测试)
摘要: Windows Installer 在C:WindowsInstaller模拟用户(并使用模拟用户的设备映射)时访问 MSI 文件,并信任这些文件来执行提升/特权操作,例如注册表项创建。非特权用户可能会滥用这一点来获取SYSTEM特权。
此漏洞已通过 Windows 2020 年 9 月安全更新修复。
几个月前,Windows Installer 中的一个有趣漏洞(来自Adrian Denkiewicz)让Jonas Lykkegård想起了他在 2020 年发现的一个漏洞,我曾协助利用该漏洞。虽然有点旧(2020 年 9 月修补),但此漏洞仍然很有趣,部分原因是它不是常见的“敏感资源是用户可写的”或“特权进程无需模拟即可访问用户资源”,而是存在于 msiexec 操作中模拟用户时执行。它的利用也有点棘手——但也很有趣。
Windows Installer ( ) 在安装时msiexec.exe为托管包创建 MSI 文件。C:WindowsInstaller这些包不是用户可写的,并且当需要对关联产品执行维护操作时,安装程序在某种程度上信任这些包。
但是,当非特权用户从 中的 MSI 文件触发维护操作时C:WindowsInstaller,Windows Installer 将在模拟用户并使用模拟用户的设备映射时访问 MSI 文件。
(过度)简化的总结是:设备映射是一组符号链接(在对象管理器中,而不是在文件系统上),它们将 MS-DOS 设备名称(例如 或 )映射到相应的设备对象(例如C:)D:,DeviceHarddiskVolume1因此当C:DirFile.ext使用类似路径时,C:将解析为适当的设备。虽然系统有一个“全局”设备映射,但还有一个每会话设备映射,允许用户执行诸如将网络驱动器映射到 之类的操作,该Z:映射仅存在于用户的会话中。事实证明,非特权用户进程可以C:在其会话的设备目录中创建对象符号链接,从而重定向会话中其他进程以及模拟它的进程的后续文件访问。
回到 CVE-2020-0911 中的 Windows Installer 行为,我们看到特权进程在模拟非特权用户的同时msiexec访问文件:.msi
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
Procmon 显示 msiexec 在模拟用户时访问 MSI 文件
但是,特权进程(没有模拟)执行的后续操作可能基于它在文件中读取的数据.msi,例如创建/覆盖注册表项:
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
Procmon 显示 msiexec 将注册表项设置为 SYSTEM
因此,MSI 文件的读取/解析是在模拟非特权用户的情况下执行的,但后续基于从 MSI 文件读取的数据的操作是以完全权限执行的。
SYSTEM非特权用户可能会滥用此功能,通过更改用户设备映射并使用对象目录和对象符号链接将 MSI 文件访问重定向到任意文件,使Windows Installer 执行任意维护操作(例如注册表项创建)。。
然而,利用这个错误并不像创建符号链接那么简单,因为有一些障碍需要克服:
-
更改C:当前会话的映射会对该会话中的其他进程产生副作用,这可能会导致行为异常(并最终使会话无法使用)
-
与经常访问的目录中的大文件重定向相同,例如C:和C:Windows:这可能会在目标进程到达感兴趣的点之前中断目标进程,以及其他进程(如果它们受相同的设备映射的约束)
-
修改后的 MSI 文件不能与原始文件相差太大(仍需要匹配产品 ID 等),否则安装程序将出错并停止
为了解决前两个限制,Jonas 提出了一种执行设备映射重定向的巧妙方法:
目标 MSI 文件的重定向C:Windowsinstallerc63eb.msi有多个部分,因此更容易逐步查看。最初,DosDevice会话的对象目录仅包含指向对象目录的链接Global??:
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
WinObj 显示仅具有全局链接的会话的 DosDevice 目录
通过在此目录中创建C:对象链接,访问(在此会话中)将被C:whatever重定向到文件系统上的临时文件夹:
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
WinObj 显示会话的 DosDevice 目录以及附加的 C: 链接
此临时文件夹包含以原始C:根目录中的所有文件夹命名的结点:
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
这些交汇点中的每一个都指向相应的原始文件夹(使用Global设备映射),除了一个:属于我们要重定向的路径一部分的文件夹(此处Windows为C:Windows):
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
该连接点指向RPC Control. 这个“主”对象目录仅包含一个条目:与目标路径中的下一项相对应的链接(此处installer为C:Windowsinstaller):
WinObj 显示带有安装程序链接的对象目录
该“主”对象目录有一个影子对象目录(此处称为“辅助”目录),如果在“主”目录中找不到资源,则该目录用作后备。“辅助”目录具有原始文件系统文件夹的所有项目的链接C:Windows,每个链接都指向文件系统上的原始项目:
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
对象目录和影子对象目录的这种组合允许重定向主目录中的特定文件或文件夹,同时将所有其他条目重定向到影子/辅助目录中各自的原始文件系统对应项:当未找到项目时在主目录中,将使用辅助目录。虽然不是绝对必要的(我们可以只使用单个对象目录并更改内部的目标符号链接),但它使得在某些情况下添加和更改链接变得更容易。
主目录中的符号链接installer指向另一对对象目录(主目录和辅助目录),这次反映了原始C:Windowsinstaller文件系统文件夹:
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
在这一对的主目录中,c63eb.msi链接指向我们希望 Windows Installer 进程加载的恶意文件(同时认为它是从受信任的系统目录加载该文件),此处C:Tempc63eb.msi。(注:inprogressinstallinfo.ipi最初在测试期间用于机会锁,但最终没有必要。)
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
显示用于重定向的挂载点、对象目录和符号链接链的架构
在实施此重定向之前,当前会话中的现有进程将使用该Global??目录作为其设备映射,使用未记录的调用来NtSetInformationProcess设置该进程的设备映射:
bool SetProcessDeviceMap(HANDLE hDir, HANDLE hProc = GetCurrentProcess()) {
PROCESS_DEVICEMAP_INFORMATION DeviceMap = { hDir };
NTSTATUS status = NtSetInformationProcess(hProc,
ProcessDeviceMap,
&DeviceMap,
sizeof(DeviceMap));
return status == 0;
}
这允许其他进程使用全局设备映射继续正常运行(只要它们不需要访问特定于会话的设备),但新进程(在会话中或模拟它)将使用伪造的目录结构。此外,对于此过程,对现有文件和文件夹的访问将在某种程度上正常工作,除了C:Windowsinstallerc63eb.msi重定向到的特定目标文件之外C:Tempc63eb.msi。
至于 MSI 文件,在 PoC 中,我们选择仅对现有 MSI 文件进行“二进制修补”并替换创建的注册表项,为 创建注册表项,然后触发崩溃以执行有效负载Image File Execution Options(WerFault.exe运行SYSTEM时WerFault.exe)作为SYSTEM进程崩溃的用户第二次)。
对此的唯一要求(几乎总是满足)是在计算机上至少安装一个产品/受管软件包。对于我们的 PoC,我们的目标是 Visual C++ 2019 可再发行 x64 中的最小运行时包,因为它的安装非常普遍。但请注意,该漏洞显然不是该软件包特有的,几乎任何 MSI 软件包都可以使用相同的方法。
由于目标注册表路径比要替换的路径长,因此使用注册表项符号链接来保持注册表路径较短:
$RegSymlink = [NtApiDotNet.NtKey]::CreateSymbolicLink("RegistryMachineSOFTWAREMicrosoftTracingaabcdefghijklmnop", $null, "REGISTRYMachineSOFTWAREMicrosoftWindows NTCurrentVersionImage File Execution Options")
这将创建所需注册表路径的替代路径,该替代路径的长度与MSI 文件中使用的
HKLM:SOFTWAREMicrosoftTracingaabcdefghijklmnopWerFault.exe
HKLM:SOFTWAREMicrosoftDevDivVCServicing14.0RuntimeMinimum
它简化了所需的二进制修补,因为现在可以使用简单的字符串匹配/替换。
-
-
创建指向目标注册表项和值的注册表项符号链接(注册表项Debugger的属性)
Image File Execution Options
WerFault.exe
-
修补二进制 MSI 文件以替换注册表项/条目路径、名称和值
-
将用户设备映射更改为重定向C:,C:Windows并C:WindowsInstaller通过对象目录和对象符号链接,并更改现有进程的设备映射,以便它们继续不受干扰地运行
-
msiexec在 MSI 文件上运行C:WindowsInstaller(但由于重定向,将访问修改后的文件)
-
提升后的用户msiexec将使用伪造的 MSI 文件(相信它是可信的)并创建所需的注册表项
-
触发崩溃来执行WerFault.exe- 及其“调试器”又名有效负载 - 作为SYSTEM
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
Procmon 显示 msiexec 访问假 MSI 文件
![Windows Installer 任意内容操纵权限提升 (CVE-2020-0911) Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)]()
Procmon 显示 msiexec 创建调试器注册表项
PoC 利用此漏洞创建所需的注册表项,然后触发崩溃以执行与 关联的调试器WerFault.exe(C:xz.exe它是 的副本payload.exe)SYSTEM。
注意:此存储库中提供的源代码是发送给 Microsoft 的原始代码;它可能需要进行调整,因为 C++ 代码需要Jonas 的漏洞利用工具包,该工具包当时尚未公开,并且可能与已发布的版本略有不同。
PoC 针对 VC++ 2019 最低运行时 x64 包。如上所述,该漏洞与这个特定的软件包无关 - 但选择这个软件包进行演示是因为它的安装非常普遍。
以下是该 PoC 在未打补丁的 Windows 10 1909 上运行的视频:
补丁:
Microsoft 已发布补丁和通报。用户应通过常规渠道应用更新。
参考
https://portal.msrc.microsoft.com/en-us/security-guidance/advisory/CVE-2020-0911
时间线
2020-05-29:初步报告发送给供应商
2020-05-29:供应商确认收到报告
2020-10-09:供应商发布修复和建议
2023-07-06:本文发表
原文始发于微信公众号(Ots安全):Windows Installer 任意内容操纵权限提升 (CVE-2020-0911)
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
点赞
https://cn-sec.com/archives/1863101.html
复制链接
复制链接
-
左青龙
- 微信扫一扫
-
-
右白虎
- 微信扫一扫
-
评论