2024年2月13日,周二补丁期间,微软根据Jan Vojtěšek与Avast所做的安全报告披露了CVE-2024-21338,这是一个新的Windows “管理员到内核”权限提升漏洞,该漏洞允许恶意行为者,在本例中,主要是Lazarus 组织与朝鲜合作,通过其FudModule.dll rootkit 获取内核访问权限。我们都知道BYOVD (“自带易受攻击的驱动程序”)意识形态在世界各地被威胁行为者和恶意软件开发人员广泛使用,他们利用自带的、已签名的、易受攻击的驱动程序来实现内核访问的能力,但这超越BYOVD。该技术适用于系统中已经安装的Windows驱动程序:见appid.sys ,它是Windows AppLocker最初使用的驱动程序,来自微软网站,“ AppLocker帮助您控制用户可以运行哪些应用程序和文件”。
CVE -2024-21338漏洞利用通过IOCTL(“输入输出控制”)通信调用appid.sys驱动程序内的特定函数,具体来说,可以从易受攻击的IOCTL控制代码0x22A018调用AipSmartHashImageFile函数。通过使用特制的输入缓冲区调用控制代码,我们能够破坏_ KTHREAD线程上下文中的PreviousMode字段。PreviousMode字段确定直接系统调用 ( Nt, Zw ) 是由内核还是用户调用。考虑到这一点,我们现在能够调用直接系统调用并使它们影响操作系统的内核,从而使恶意威胁行为者能够访问受害者的内核。
分析
Lazarus制作的FudModule.dll Rootkit的主要目的是通过篡改 EDR/防病毒产品或隐藏其自己的功能来规避 EDR/防病毒产品的检测,如“ Lazarus 和 FudModule Rootkit:超越 BYOVD”中所示。然而,在 Avast 发表的一篇“管理员到内核零日”帖子中,我们不会在这篇文章中关注 Rootkit 本身的工作原理。我们将探讨appid.sys漏洞的工作原理、如何利用该漏洞,以及 MSRC 补丁在最新版本的 Windows 上修复该漏洞的方法。
2024年2月13日,周二补丁期间,微软安全响应中心(MSRC)披露了一个名为“ CVE-2024-21338 ”的全新漏洞,该漏洞允许攻击者通过发送特制的指令来读写内核内存。小工具通过允许 IOCTL(输入输出控制)通信的公开函数。
首先,对于 Windows 上通过 IOCTL 进行的任何通信,需要为我们正在通信的目标驱动程序打开一个句柄。在这种情况下,通过分析IDA Pro上的appid.sys(AppLocker)驱动程序,我们可以在DriverEntry函数上看到,我们需要打开句柄的对象是“ \Device\AppID ”,如屏幕截图所示以下。
然而,当我们尝试通过NtCreateFile打开管理员到“ \Device\AppID ”的句柄时,我们会遇到NTSTATUS代码0xC0000022 (STATUS_ACCESS_DENIED),这意味着管理员用户没有正确的访问权限来打开AppID 设备的句柄。这让我们产生疑问,我们需要哪些权限才能成功打开它的句柄。通过调查漏洞函数“ AipSmartHashImageFile ”来尝试找出为什么我们无法打开“ \Device\AppID ”的设备句柄,我们发现通过“AipSmartHashImageFile”函数的外部引用,“ AipDeviceIoControlDispatch ”函数可以可以找到,它与通过Device句柄处理所有对驱动程序的IOCTL调用的函数有关。
通过打开这个调用,我们可以看到“ AipSmartHashImageFile ”函数正在通过“ 0x22A018 ”的IOCTL代码被调用,如下图所示。
好的,现在我们有了 IOCTL 代码,我们可以用它做什么呢?除了通过“ NtDeviceIoControl ”向该特定函数发送控制请求外,IOCTL 代码还有自己的结构。通过将 IOCTL 代码分解为“ AipSmartHashImageFile ”函数,根据 IOCTL Microsoft 文档,我们可以看到该 IOCTL 代码需要0x0002 ( FILE_WRITE_ACCESS ) 权限才能调用,这意味着 – 最有可能 – 打开一个句柄我们的驱动程序需要相同的权限,但是哪个用户在 AppID 设备上为我们提供了此权限?你可能会问。通过使用SysInternals Suite中的“ WinObj ”工具,我们可以列出当前安装中存在的所有系统对象,这也包括所有设备和所有驱动程序。通过检查“ WinObj ”应用程序上“ AppID ”设备的权限,我们可以看到“ Administrators ”组在AppID的ACL(访问控制列表)中没有所需的“ Write ”权限,如屏幕截图所示以下。
而且我们还可以看到,“ LOCAL SERVICE ”用户名确实具有所需的“ Write ”权限,可以通过IOCTL代码成功访问并调用我们需要的函数。
考虑到这一点,我们现在进入利用阶段,我们将通过“令牌模拟”来利用“ Windows访问令牌”,并将精心设计的小工具发送到“ AipSmartHashImageFile ”函数。
开发
利用阶段从获取“ \Device\AppID ”句柄的访问权限开始,为此,我们需要在进程中访问“ LOCAL SERVICE ”,为了获得此访问权限,我们需要应用一些访问令牌模拟技术来实现我们流程中的“本地服务”许可。
什么是Windows 访问令牌?根据Microsoft 文档,访问令牌是“描述 进程 或线程安全上下文 的 对象。令牌中的信息包括与进程或线程关联的用户帐户的身份和特权。当用户登录时,系统通过将用户的密码与安全数据库中存储的信息进行比较来验证用户的密码。如果密码通过 验证,系统会生成访问令牌。代表该用户执行的每个进程都有该访问令牌的副本”。
这些令牌可以通过检查进程是否具有特定权限来从 Windows 中的远程进程中窃取它们。在这种情况下,从提升(管理员)到“ NT AUTHORITYSYSTEM ”(S-1-5-18),需要两个权限:“ SeDebugPrivilege ”和“ SeAssignPrimaryTokenPrivilege ”。
“winlogon.exe”进程公开了具有这两种权限的令牌,因为根据设计,该进程作为 SYSTEM 运行,因为它需要操作 Windows 的登录状态,并且用户可以轻松地与之交互,从而允许用户复制“NT AUTHORITY”来自winlogon 的SYSTEM” 访问令牌。
使用“ DuplicateTokenEx ”成功复制 SYSTEM 令牌后,我们现在可以通过查找具有上述权限的任何令牌来访问“ NT AUTHORITYLOCAL SERVICE ” (S-1-5-19) 访问令牌:“ SeDebugPrivilege ” 和“ SeImpersonatePrivilege ”,通常情况下,大多数“svchost.exe”进程都以“ NT AUTHORITYLOCAL SERVICE ”身份运行,因此找到一个应该非常容易和快速。
现在我们拥有“ NT AUTHORITYLOCAL SERVICE ”访问权限,这意味着我们对“ AppID ”设备句柄(“ \Device\AppID ”)和0x22A018控制代码拥有“写入”访问权限,现在我们可以成功打开所提到的设备句柄的句柄。通过打开正确的句柄并访问“ AipSmartHashImageFile ”函数,我们可以知道构造有效负载以触发“ PreviousMode ”字节内存“损坏”。
PreviousMode是每个_KTHREAD结构中存在的一个字段,指示系统调用是从KernelMode还是UserMode调用。考虑到这一点,一些Nt或Zw (直接)系统调用通过检查当前线程的“ PreviousMode ”字段来检查“ PreviousMode ”值,以下是从“ ntoskrnl.exe ”反汇编中获取的“ NtWriteVirtualMemory ”系统调用代码片段的示例:
“ PreviousMode ”字段是一个简单的枚举,有两个成员“ UserMode ”和“ KernelMode ”,即KernelMode为 0,UserMode为 1。知道我们有可能在内存当前的_KTHREAD结构中修改这个值,我们深入研究了解该字段的内存损坏实际上是如何工作的。
允许“ PreviousMode ”漏洞实际发挥作用的罪魁祸首是“ AppHashComputeImageHashInternal ”,它由“ AipSmartHashImageFile ”函数内的“ AppHashComputeFileHashesInternal ”函数调用,如下面的屏幕显示所示。
正如我们在下面的屏幕截图中看到的,两个参数通过这些函数链传递,最后是“ AppHashComputeImageHashInternal ”,它根据用户控制的缓冲区执行用户控制的函数指针,在本例中,在我们对0x22A018控制代码的调用中进行控制。
现在,我们不能编写一个用户模式 shellcode 发送到控制代码,告诉当前线程的“ PreviousMode ”减少到 0 吗?不幸的是,我们不能。了解kCFG(内核控制流防护)和SMEP(管理程序模式执行保护)。
-
SMEP(管理员模式执行保护)不允许我们在较高权限级别下执行用户模式下的代码,这将不允许我们执行用户模式 shellcode 来实现我们想要的目的。
-
kCFG (内核控制流防护)不允许我们调用任意或未经验证的函数指针,特别是那些指向用户模式地址或有效内核函数已建立的 CFG 位图之外的位置的指针。此机制可确保根据控制流完整性策略检查所有间接函数调用,从而防止将执行流转移到恶意或意外代码段的利用。
考虑到这两种保护,我们现在需要找到有效内核函数的CFG 位图中存在的函数,使其能够用作间接函数调用的合法目标。理想情况下,该函数应该提供可用于进一步利用的功能,在本例中为内存操作,同时遵守kCFG和SMEP设置的约束。
感谢之前对此事的研究,“ Windows AppLocker 驱动程序权限提升 (CVE-2024-21338) ” 文章详细介绍了如何在CFG 位图中查找有效的CFG函数。我们的PoC中选择的函数是“ ExpProfileDelete ”,它是一个有效的CFG函数,它的功能实际上非常适合我们想要的功能。通过查看“ ExpProfileDelete ”函数的反汇编:
我们可以看到该函数接收一个参数,该参数将传递给函数“ ObfDereferenceObject ”,然后,该参数将导致作为参数传递给“ ExpProfileDelete ”函数的地址递减,从而导致“ PreviousMode ”地址数据从1到0,导致“ NtWriteVirtualMemory ”和“ NtReadVirtualMemory ”系统调用将其调用解释为来自内核模式。允许恶意用户控制利用此漏洞的系统的内核空间内存。
修补
微软安全响应中心(MSRC)2月份发布的补丁在“ AipSmartHashImageFile ”调用之前添加了“ ExGetPreviousMode ”检查,这可以防止用户模式发起的调用触发上述回调函数。下图显示了在较新版本的 Windows 上相同控制代码的反汇编。
图片来源:https://decoded.avast.io/janvojtesek/lazarus-and-the-fudmodule-rootkit-beyond-byovd-with-an-admin-to-kernel-zero-day/
通过使用显示两个二进制文件之间差异的BinDiff工具,我们还可以看到补丁中应用的更改,这只是“ ExGetPreviousMode ”检查。
图片来源:https://nero22k.github.io/posts/windows-applocker-driver-elevation-of-privilege-cve-2024-21338/#patch-diffing
概念证明
根据显示的所有概念,精心设计了概念验证 (PoC) 以显示此漏洞的严重性。下面的图片显示了 PoC 执行的调用堆栈,遵循上面帖子中显示的相同原则。
PoC 的链接可在 GitHub 上找到:https://github.com/hakaioffsec/CVE-2024-21338。
结论
总之,CVE-2024-21338漏洞在 Windows 系统中带来了显着的特权提升威胁,特别是被 Lazarus 组织利用来绕过 EDR 和防病毒等传统安全措施。该漏洞展示了一种复杂的技术,超越了已经令人担忧的 BYOVD 方法,它操纵内核中的“ PreviousMode ”字段来实现未经授权的访问,同时还使用扩展令牌模拟技术,从而分别实现从管理到内核的执行。微软的回应,在二月份的更新中加入了一个关键补丁,凸显了网络安全专业人员和威胁行为者之间正在进行的猫鼠游戏。CVE -2024-21338研究帮助我们更多地了解此类特定漏洞如何在野外发生。
参考
-
https://decoded.avast.io/janvojtesek/lazarus-and-the-fudmodule-rootkit-beyond-byovd-with-an-admin-to-kernel-zero-day/
-
https://nero22k.github.io/posts/windows-applocker-driver-elevation-of-privilege-cve-2024-21338/
-
https://research.nccgroup.com/2020/05/25/cve-2018-8611-exploiting-windows-ktm-part-5-5-vulnerability-detection-and-a-better-read-write-primitive/
-
https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-21338
-
https://malpedia.caad.fkie.fraunhofer.de/details/win.fudmodule
原文始发于微信公众号(Ots安全):Windows 管理员到内核的权限提升漏洞分析 (CVE-2024-21338)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论