Windows注册表冒险 #8:hive内存损坏的实战利用
引言
在之前的博客文章中,我们重点讨论了注册表的一般安全分析以及如何有效寻找其中的漏洞。在这里,我们将注意力转向基于hive的内存损坏漏洞的利用,即那些允许攻击者覆盖活动hive映射中数据的漏洞。这是一类Windows注册表特有的问题,但也具有足够的通用性,使得这里描述的技术适用于我过去的17个漏洞,以及未来可能出现的任何类似漏洞。众所周知,hive在低级内存管理(如何以及在何处映射到内存)、自定义分配器处理已分配和释放的内存块以及存储数据的性质方面表现出非常特殊的行为。所有这些使得从攻击安全的角度来看,利用这类漏洞特别有趣,这也是我想在这里详细描述的原因。
与任何其他类型的内存损坏类似,绝大多数hive内存损坏问题可以分为两类:空间违规(如缓冲区溢出)和时间违规(如释放后使用条件)。
在本文中,我们将选择最有前途的漏洞候选,然后为其创建一个分步利用,将常规用户的权限从中等完整性级别提升到系统级权限。我们的目标是Windows 11,并额外要求成功绕过所有现代安全缓解措施。我之前在OffensiveCon 2024上以“Windows内核中注册表漏洞的实战利用”为题介绍了这个主题,这篇博客文章可以视为该演示的补充和扩展。对该主题深感兴趣的读者鼓励查看该演示的幻灯片和录音。
从哪里开始:潜在选项的高级概述
让我们从回顾一些关键点开始。正如您可能记得的,Windows注册表单元分配器(即内部的HvAllocateCell、HvReallocateCell和HvFreeCell函数)的操作方式非常有利于利用。首先,它完全缺乏任何针对内存损坏的防护措施;其次,它没有任何随机性元素,使其行为完全可预测。因此,不需要使用任何“hive喷洒”或其他典型堆利用中的类似技术——如果我们在测试机器上实现了所需的单元布局,它将在其他计算机上无需额外步骤即可重现。潜在的例外可能是在HKLM和HKU中的全局共享hive上执行攻击,因为我们不知道它们的初始状态,并且可能由于其他应用程序同时执行的操作而产生一些随机性。尽管如此,即使这也不应构成特别重大的挑战。我们可以安全地假设,安排hive的内存布局是直接的,并且如果我们在其中具有某种内存损坏能力,只要有耐心和实验,我们最终将能够覆盖任何类型的单元。
经典内存损坏漏洞的利用通常涉及以下步骤:
- 初始内存损坏原语
- ???
- 利润(以任意代码执行、权限提升等形式)
利用开发人员的任务是填补此列表中的空白,设计导致期望目标的中间步骤。通常有几个这样的中间步骤,因为考虑到当前的安全状态和缓解措施,漏洞很少直接从内存损坏一步导致代码执行。相反,采用逐步开发更强原语的策略,其中最终链可能如下所示:
初始内存损坏原语 → 更强的内存损坏原语 → 任意读/写 → 代码执行
在此模型中,第二/第三步通过找到另一个有趣的对象,安排其在被覆盖的缓冲区附近分配,然后以创建新原语的方式损坏它来实现。然而,在hive的情况下,我们在这方面的选项似乎有限:我们假设可以完全控制hive中任何单元的表示,但问题是从利用的角度来看,其中没有立即有趣的数据。例如,regf格式不包含任何直接影响控制流的数据(例如函数指针),也不包含虚拟内存中的任何其他地址,这些地址可以通过某种聪明的方式被覆盖以改进原始原语。下图描绘了我们当前的情况:
这是否意味着hive内存损坏不可利用,它唯一允许的是在孤立的hive内存视图中进行数据损坏?不完全。在以下小节中,我们将仔细考虑各种想法,即控制内部hive数据如何对系统的整体安全产生更广泛的影响。然后,我们将尝试确定可用方法中哪一种最适合在真实世界的利用中使用。
内部hive损坏
让我们首先调查覆盖内部hive数据是否如最初看起来那样不切实际。
在特权系统hive中执行仅hive攻击
需要明确的是,说hive不包含任何值得覆盖的数据并不完全准确。如果您仔细想想,情况恰恰相反——注册表存储了大量系统配置、注册服务信息、用户密码等。唯一的问题是所有这些关键数据都位于特定的hive中,即那些挂载在HKEY_LOCAL_MACHINE下的hive,以及HKEY_USERS中的一些(例如,HKU.Default,对应于System用户的私有hive)。要能够通过仅损坏regf格式数据(无需访问其他内核内存或实现任意代码执行)成功执行攻击并提升权限,必须满足两个条件:
- 漏洞必须仅通过API/系统调用触发,并且不需要对hive的二进制控制,因为我们显然对任何系统hive都没有这种控制。
- 目标hive必须包含至少一个具有足够宽松访问权限的键,允许非特权用户创建值(KEY_SET_VALUE权限)和/或新的子键(KEY_CREATE_SUB_KEY)。根据特定漏洞的先决条件,可能还需要其他一些访问权限。
在上述两点中,第一点肯定更难满足。许多hive内存损坏漏洞源于hive结构中的奇怪、不可预见的状态,这种状态只能通过从对给定文件的完全控制开始的“离线”方式生成。仅API的漏洞似乎相对罕见:例如,在我17个基于hive的内存损坏案例中,理论上只有不到一半(具体是8个)可以仅通过对现有hive的操作触发。此外,仔细观察发现,其中一些不满足针对系统hive所需的其他条件(例如,它们仅影响差异hive),或者非常不实用,例如需要分配超过500 GB的内存,或需要许多小时才能触发。实际上,在广泛的漏洞范围内,只有两个非常适合直接攻击系统hive:CVE-2023-23420(在报告的“操作事务性重命名键的子键”部分讨论)和CVE-2023-23423(在“释放键节点的浅拷贝与CmpFreeKeyByCell”中讨论)。
关于第二个问题——可写键的可用性——攻击者的情况要好得多。这有三个原因:
- 要成功对系统键执行仅数据攻击,我们通常不限于一个特定的hive,而是可以选择任何适合我们的hive。利用大多数(如果不是全部)挂载在HKLM下的hive中的hive损坏,将使攻击者能够提升权限。
- Windows内核内部通过首先在注册表树中进行完整路径查找来实现键打开过程,然后才检查所需的用户权限。访问检查仅针对特定键的安全描述符执行,而不考虑其祖先。这意味着为键设置过于宽松的安全设置会自动使其易受攻击,因为根据此逻辑,它不会从其祖先键获得额外保护,即使它们具有更严格的访问控制。
- HKLM\SOFTWARE和HKLM\SYSTEM hive中存在大量用户可写键。它们不存在于HKLM\BCD00000000、HKLM\SAM或HKLM\SECURITY中,但正如我上面提到的,只有一个这样的键就足以成功利用。
要找到此类公开可访问键的具体示例,有必要编写自定义工具。该工具应首先递归列出低级\Registry\Machine和\Registry\User路径中的所有现有键,同时以最高可能的权限操作,理想情况下作为System用户。这将确保该进程可以看到注册表树中的所有键——即使是那些隐藏在受限父键后面的键。不值得尝试枚举\Registry\A的子键,因为对它的任何引用都被Windows内核无条件阻止。类似地,除非对容器化应用程序使用的差异hive攻击感兴趣,否则可能可以跳过\Registry\WC。一旦我们有了所有键的完整列表,下一步是验证哪些键可由非特权用户写入。这可以通过读取它们的安全描述符(使用RegGetKeySecurity)并手动检查其访问权限(使用AccessCheck)来实现,或者通过将此任务完全委托给内核,并仅以常规用户权限尝试以所需权限打开每个键。无论哪种情况,我们最终都应该能够获得可用于损坏系统hive的潜在键列表。
根据我的测试,在当前Windows 11系统上,HKLM内大约有1678个键授予普通用户创建子键的权利。其中,1660个位于HKLM\SOFTWARE,18个位于HKLM\SYSTEM。一些示例包括:
- HKLM\SOFTWARE\Microsoft\CoreShell
- HKLM\SOFTWARE\Microsoft\DRM
- HKLM\SOFTWARE\Microsoft\Input\Locales(及其一些子键)
- HKLM\SOFTWARE\Microsoft\Input\Settings(及其一些子键)
- HKLM\SOFTWARE\Microsoft\Shell\Oobe
- HKLM\SOFTWARE\Microsoft\Shell\Session
- HKLM\SOFTWARE\Microsoft\Tracing(及其一些子键)
- HKLM\SOFTWARE\Microsoft\Windows\UpdateApi
- HKLM\SOFTWARE\Microsoft\WindowsUpdate\UX
- HKLM\SOFTWARE\WOW6432Node\Microsoft\DRM
- HKLM\SOFTWARE\WOW6432Node\Microsoft\Tracing
- HKLM\SYSTEM\Software\Microsoft\TIP(及其一些子键)
- HKLM\SYSTEM\ControlSet001\Control\Cryptography\WebSignIn\Navigation
- HKLM\SYSTEM\ControlSet001\Control\MUI\StringCacheSettings
- HKLM\SYSTEM\ControlSet001\Control\USB\AutomaticSurpriseRemoval
- HKLM\SYSTEM\ControlSet001\Services\BTAGService\Parameters\Settings
如我们所见,有相当多的可能性。列表中的第二个键HKLM\SOFTWARE\Microsoft\DRM在过去有些流行,因为它之前被James Forshaw用于演示他在2019-2020年发现的两个漏洞(CVE-2019-0881,CVE-2020-1377)。随后,我也将其用作触发与注册表虚拟化相关的某些行为的方式(CVE-2023-21675,CVE-2023-21748,CVE-2023-35357),并作为填充SOFTWARE hive到其容量的潜在途径,从而作为利用另一个漏洞(CVE-2023-32019)的一部分导致OOM条件。此键的主要优点是它存在于所有现代版本的系统中(至少从Windows 7开始),并且它向所有用户(Everyone组,也称为World或S-1-1-0)授予广泛权限。上面提到的其他键也允许常规用户写入操作,但它们通常通过其他可能更受限制的组(如Interactive(S-1-5-4)、Users(S-1-5-32-545)或Authenticated Users(S-1-5-11))来实现,这可能需要注意。
除了全局系统hive之外,我还发现了HKCU\Software\Microsoft\Input\TypingInsights键在每个用户hive中都存在的奇怪情况,它允许系统