一、漏洞全景:补丁日后的“回马枪”

2026 年 7 月 14 日,微软发布了当月补丁星期二更新,修复了数百个 CVE。然而就在补丁发布后数小时,安全研究员 Chaotic Eclipse(GitHub 账号 MSNightmare)公开了一个名为 LegacyHive 的本地权限提升(LPE)概念验证代码。该 PoC 针对的是 Windows 用户配置文件服务(ProfSvc),并且据 SecurityWeek、CrowdStrike、SOC Prime 等机构确认,它在安装了 7 月累积更新后的所有受支持 Windows 桌面版与服务器版上依然有效。

LegacyHive 的核心危害在于:一个标准(非管理员)用户能够胁迫一个以 SYSTEM 权限运行的服务,把另一个用户(可以是管理员)的注册表 Hive 文件加载进自己的注册表空间,并获得完整的读写权限。这打破了 Windows 用户配置文件隔离这一基础安全边界。

需要强调的是,CrowdStrike 在评估中指出,公开发布的 PoC 代码被刻意限制(deliberately restricted)——它需要第二个标准用户的凭据,且仅针对 UsrClass.dat Hive。研究员声称其原始完整版利用不需要额外用户凭据,即可强制 ProfSvc 加载任意 Hive。这一区别在评估实际风险时至关重要。

从威胁模型看,LegacyHive 是一个后渗透(post-compromise)本地提权漏洞:攻击者必须先在目标机器上获得代码执行能力。这意味着它并非远程入侵入口,但在共享桌面、跳板机、终端服务器(RDS Host)、开发工作站、教室与呼叫中心等多用户环境中,它能把一个低权限立足点迅速放大为管理员甚至 SYSTEM 级别的控制权。

二、ProfSvc 架构与 Hive 加载机制

2.1 用户配置文件服务职责

Windows User Profile Service(ProfSvc)是一个以 SYSTEM 权限运行的服务,托管在共享进程 svchost.exe 中。它的核心职责是管理用户配置文件的生命周期:在用户登录时加载其注册表 Hive(NTUSER.DATUsrClass.dat),在用户注销时卸载这些 Hive。它还负责处理“以其他用户身份运行进程”(RunAs / CreateProcessAsUser)场景下目标用户配置文件的按需加载。

每个 Windows 用户账户携带两个关键 Hive 文件:

  • NTUSER.DAT:对应用户的 HKEY_CURRENT_USER 根 Hive,存储桌面设置、环境变量、用户级软件配置等。
  • UsrClass.dat:对应用户的 HKEY_CLASSES_ROOT(Classes Hive),存储文件类型关联、COM 对象注册、Shell 扩展等。该文件位于用户配置文件的 AppData\Local\Microsoft\Windows 目录下。

这两个文件在正常情况下仅对所属账户(及 SYSTEM)可访问,构成了用户间配置数据隔离的文件层基础。

2.2 Hive 加载架构图

下面的时序图展示了正常情况下用户登录与跨用户进程创建时,ProfSvc 加载 Hive 的完整流程:

sequenceDiagram autonumber participant U as 用户进程(Logon/RunAs) participant LSASS as LSASS / Winlogon participant ProfSvc as ProfSvc(SYSTEM) participant Kernel as 配置注册表内核 participant FS as 文件系统(NTUSER.DAT/UsrClass.dat) U->>LSASS: 发起登录 / CreateProcessAsUser(目标用户) LSASS->>ProfSvc: 通知加载目标用户配置文件 ProfSvc->>FS: 解析并打开目标用户 Hive 文件路径 FS-->>ProfSvc: 返回文件句柄 ProfSvc->>ProfSvc: 访问检查 CheckFullAccessOnFile alt 请求方有完全访问权限 ProfSvc->>Kernel: NtLoadKey3(用户模拟令牌, KEY_READ|KEY_WRITE) else 请求方无完全访问权限(只读场景) ProfSvc->>Kernel: NtLoadKeyEx(SYSTEM身份, 完全访问) end Kernel-->>ProfSvc: Hive 挂载到 HKEY_USERS\<SID> ProfSvc-->>LSASS: 配置文件就绪 LSASS-->>U: 用户环境准备完成

关键点在于 ProfSvc 加载 Hive 时调用的两个底层函数:

  • NtLoadKeyEx:较旧的 Hive 加载函数,不支持用户模拟(impersonation),因此 Hive 总是以调用者(即 SYSTEM)身份加载,获得完全访问权限。
  • NtLoadKey3:较新的函数,支持用户模拟,可以指定一个用户令牌,使 Hive 以该用户身份加载,访问权限受限于该令牌。

ProfSvc 在决定使用哪个函数时,会进行一次 CheckFullAccessOnFile 访问检查,判断请求用户对目标 Hive 文件是否具有完全访问权限。这个看似合理的分支逻辑,正是漏洞的温床。

2.3 漏洞代码逻辑剖析

根据 0patch 的逆向分析,漏洞代码在所有受支持 Windows 版本上的逻辑可概括如下(r14 寄存器存放用户令牌,0 表示服务内部调用):

// 伪代码:profsvc.dll 中的 Hive 加载逻辑
NTSTATUS LoadUserHive(HANDLE UserToken, PWSTR HiveFilePath) {
    if (UserToken == NULL) {
        // 服务自身发起,无可模拟令牌 -> 直接以 SYSTEM 加载
        return NtLoadKeyEx(HiveFilePath, ...);  // 完全访问, SYSTEM 身份
    }

    // 有用户令牌:检查用户对 Hive 文件是否有完全访问权限
    BOOL hasFullAccess = CheckFullAccessOnFile(UserToken, HiveFilePath);

    if (hasFullAccess) {
        // 有完全访问权限 -> 模拟用户身份加载
        return NtLoadKey3(UserToken, HiveFilePath, KEY_READ | KEY_WRITE, ...);
    } else {
        // 【漏洞核心】无完全访问权限 -> 退回 SYSTEM 身份加载
        // 本意是兼容只读 Mandatory Profile 场景(NTUSER.MAN)
        return NtLoadKeyEx(HiveFilePath, ...);  // 完全访问, SYSTEM 身份
    }
}

0patch 团队对此的点评一针见血:这段代码表面上像一个标准的安全检查(“用户有权限就走左路,没权限就走右路”),但实际语义是“用户有权限就用用户身份加载,没权限就用 SYSTEM 身份加载”——因此它几乎总能在所有典型条件下成功加载文件。换言之,直接在所有情况下都以 SYSTEM 加载效果完全相同,这个“安全分支”不仅没有提供保护,反而因为引入了 CheckFullAccessOnFile 与实际 NtLoadKeyEx 调用之间的时间窗口,为 TOCTOU 攻击打开了大门。

据 0patch 推测,这段代码的历史成因可能是:多年前某位微软程序员为修复一个类似 LegacyHive 的符号链接提权,添加了“有用户令牌就模拟”的检查;但该检查破坏了学校机房、公共电脑等使用的 Mandatory User Profile(强制用户配置文件,NTUSER.MAN 只读)场景。为了不破坏该场景,程序员补加了“无法完全访问就退回 SYSTEM 加载”的分支——却没意识到这第二个分支完全抵消了第一个分支的安全意义。

三、TOCTOU 竞态条件深度分析

3.1 TOCTOU 漏洞模型

TOCTOU(Time-of-Check to Time-of-Use,检查时到使用时)是 CWE-362 竞态条件的经典子类。其核心是:程序在检查某个条件(如文件路径、权限)与使用该检查结果之间,存在一个时间窗口;攻击者若能在此窗口内篡改被检查的对象,就能使程序基于过时的检查结果执行错误的操作。

在 LegacyHive 中,TOCTOU 发生在:

  • Check(检查点)CheckFullAccessOnFile(UserToken, HiveFilePath)——ProfSvc 检查请求用户对路径 HiveFilePath 指向的文件是否有完全访问权限。
  • Use(使用点)NtLoadKeyEx(HiveFilePath, ...)——ProfSvc 实际加载该路径指向的 Hive 文件。

攻击者要做的就是:让 Check 阶段看到的文件是攻击者种植的诱饵文件(其权限导致检查失败,从而走 SYSTEM 加载分支),而在 Use 阶段让 HiveFilePath 解析到目标用户(管理员)的真实 UsrClass.dat。由于检查失败分支使用不带模拟的 NtLoadKeyEx,Hive 会以 SYSTEM 身份加载,绕过文件 ACL,最终挂载到攻击者的注册表空间。

3.2 竞态时序图

下面的时序图精确刻画了攻击者如何在 Check 与 Use 之间完成路径“狸猫换太子”:

sequenceDiagram autonumber participant A as 攻击者进程(标准用户) participant OM as Object Manager命名空间 participant ProfSvc as ProfSvc(SYSTEM) participant FS as 文件系统 participant T as 目标管理员UsrClass.dat A->>A: 种植诱饵DAT文件(权限使CheckFullAccess失败) A->>OM: 构造符号链接: 路径X -> 诱饵DAT A->>FS: 对诱饵DAT设置Oplock(机会锁) A->>ProfSvc: 触发CreateProcessAsUser(目标用户) ProfSvc->>FS: 解析路径X -> 诱饵DAT ProfSvc->>FS: CheckFullAccessOnFile(打开诱饵DAT) Note over FS: Oplock触发! ProfSvc阻塞在此 A->>A: 检测到Oplock命中(竞态窗口打开) A->>OM: 原子替换符号链接: 路径X -> 目标T的UsrClass.dat A->>FS: 释放Oplock Note over ProfSvc: Check返回: 无完全访问权限 ProfSvc->>ProfSvc: 决策: 走NtLoadKeyEx分支(SYSTEM身份) ProfSvc->>FS: NtLoadKeyEx(路径X) FS->>T: 路径X现在解析到目标T的UsrClass.dat Note over FS: SYSTEM身份打开, 绕过ACL! T-->>ProfSvc: Hive文件句柄 ProfSvc->>ProfSvc: 挂载Hive到攻击者HKEY_CLASSES_ROOT ProfSvc-->>A: Hive加载完成(读写权限) A->>A: 攻击者可读写管理员Classes Hive

3.3 竞态窗口的精确控制:Oplock

要让上述时序可靠成立,攻击者必须能精确感知 Check 阶段的发生时机,并在 Use 阶段之前完成符号链接替换。这正是 Oplock(Opportunistic Lock,机会锁) 发挥作用的地方。

Oplock 是 Windows 文件系统提供的一种客户端缓存协调机制。当攻击者对诱饵文件设置 Oplock 后,任何其他进程(包括 SYSTEM 权限的 ProfSvc)试图以冲突方式打开该文件时,Oplock 会被“破坏”,攻击者进程会收到通知,而请求方会被阻塞,直到攻击者释放 Oplock。这就给了攻击者一个可控的同步点:

  1. 攻击者创建诱饵 DAT 文件并对其设置 Oplock。
  2. 触发 ProfSvc 的 Hive 加载流程,使其路径解析到诱饵文件。
  3. ProfSvc 在 CheckFullAccessOnFile 中打开诱饵文件,Oplock 命中,ProfSvc 阻塞
  4. 攻击者检测到 Oplock 命中(竞态窗口已打开),立即原子性地替换符号链接,使其指向目标 UsrClass.dat
  5. 攻击者释放 Oplock,ProfSvc 从 CheckFullAccessOnFile 返回(结果是“无完全访问权限”)。
  6. ProfSvc 走 NtLoadKeyEx 分支,但此时路径已指向目标文件——SYSTEM 身份加载,绕过 ACL。

整个过程的核心在于:Oplock 把原本不可控的微秒级竞态窗口,变成了攻击者可主动开关的同步原语,使利用从“碰运气”变为“高可靠”。

四、Object Manager 路径操控技术分析

4.1 Windows Object Manager 命名空间

要理解 LegacyHive 如何在 Check 与 Use 之间完成路径替换,必须深入 Windows 对象管理器(Object Manager) 命名空间。对象管理器是 Windows NT 内核的子系统,负责创建、管理和命名所有内核对象(进程、线程、文件、事件、信号量、符号链接、目录对象等)。它维护着一个类似文件系统的层级命名空间,根目录为 \

关键命名空间节点包括:

  • \?? / \Global??:DOS 设备命名空间,Win32 路径(如 C:\...)在此解析。C: 实际是指向 \Device\HarddiskVolumeX 的符号链接。
  • \BaseNamedObjects:全局命名对象(事件、互斥体、信号量等)的默认目录。
  • \BaseNamedObjects\Restricted:受限命名对象目录,标准用户可在此创建对象——这一点对攻击至关重要。
  • \RPC Control:RPC 控制命名空间,标准用户同样具有 Create Object 权限,常用于符号链接攻击。
  • \Sessions\X\BaseNamedObjects:会话级命名对象目录。

对象管理器的符号链接(Object Manager Symbolic Link)与文件系统的符号链接完全不同。它通过 NtCreateSymbolicLinkObject 创建,是一个内核对象,能将一个对象管理器名称重定向到另一个对象管理器路径或设备路径。普通用户可以在自己有权限的目录(如 \RPC Control\BaseNamedObjects\Restricted)中创建此类符号链接

4.2 路径解析与“混淆代理”

当高权限进程(如 ProfSvc)打开一个用户可影响的路径时,路径解析会逐段进行。攻击者只要在路径的某一段植入符号链接,就能把剩余路径解析重定向到攻击者原本无权访问的目标。这就是经典的 Confused Deputy(混淆代理) 模型:高权限服务“代理”了攻击者的请求,却用自身权限访问了被重定向后的目标。

LegacyHive 及同类利用(如同一研究员的 BlueHammer)的典型路径操控链路为:

  1. 连接点(Junction / Mount Point)桥接:通过 NTFS 重解析点(IO_REPARSE_TAG_MOUNT_POINT)创建目录连接点,把一个 Win32 文件系统目录重定向到对象管理器目录(如 \BaseNamedObjects\Restricted)。这桥接了文件系统命名空间与对象管理器命名空间。
  2. 对象管理器符号链接注入:在受限命名空间内用 NtCreateSymbolicLinkObject 创建符号链接,把一个虚拟文件名指向真正的目标设备路径(如目标用户的 UsrClass.dat 全路径,或 \Device\HarddiskVolumeShadowCopyX\... 影子副本路径)。
  3. 路径解析劫持:当高权限进程沿连接点进入对象管理器空间,再沿符号链接解析时,最终打开的是攻击者指定的目标文件——以高权限进程的身份绕过目标文件的 ACL。

4.3 关键 NT API

下表总结了路径操控链路中用到的核心原生 API:

API 作用 权限要求
NtCreateSymbolicLinkObject 在对象管理器命名空间创建符号链接 对目标目录有 CREATE_OBJECT 权限
NtOpenDirectoryObject 打开对象管理器目录对象 对应目录的访问权限
NtCreateDirectoryObjectEx 创建/操作对象管理器目录对象 父目录权限
DeviceIoControl(FSCTL_SET_REPARSE_POINT) 设置 NTFS 重解析点(连接点) 对目录有写权限(标准用户即可)
SetOplock / NtCreateFile(OPLOCK) 设置机会锁 对文件有适当访问权限

值得注意的是,文件系统符号链接(NTFS Symlink)需要 SeCreateSymbolicLinkPrivilege(默认仅管理员),但连接点(Junction)与对象管理器符号链接标准用户即可创建。这正是此类提权链能由低权限用户发起的根本原因——攻击者总能找到标准用户可写、可创建对象的命名空间角落。

五、完整攻击链分析

5.1 前置条件

公开版 LegacyHive PoC 的利用条件为:

  1. 两个标准用户账户的凭据:攻击者当前登录账户 A(标准用户),并掌握第二个标准用户账户 B 的口令。账户 B 用于触发“以 B 身份运行进程”,从而让 ProfSvc 为 B 加载配置文件 Hive。
  2. 识别第三个目标账户 C(可以是管理员):其 UsrClass.dat 是攻击者想要劫持的目标。
  3. 目标机器上账户 B 与账户 C 的 Hive 文件存在且路径可预测。

5.2 攻击链全景

flowchart TD A[攻击者登录账户A 标准用户] --> B[掌握账户B凭据 标准用户] B --> C[识别目标账户C 管理员] C --> D[种植诱饵DAT文件\n权限使CheckFullAccess失败] D --> E[构造Object Manager符号链接\n路径X -> 诱饵DAT] E --> F[对诱饵DAT设置Oplock] F --> G[以账户B身份CreateProcessAsUser\n触发ProfSvc加载B的Hive] G --> H{ProfSvc执行CheckFullAccessOnFile\n打开诱饵DAT, Oplock命中} H --> I[攻击者检测到Oplock\n竞态窗口打开] I --> J[原子替换符号链接\n路径X -> 账户C的UsrClass.dat] J --> K[释放Oplock] K --> L[Check返回: 无完全访问权限] L --> M[ProfSvc走NtLoadKeyEx分支\nSYSTEM身份] M --> N[NtLoadKeyEx加载路径X\n实际加载账户C的UsrClass.dat] N --> O[Hive挂载到攻击者HKEY_CLASSES_ROOT\n读写权限] O --> P1[后利用1: 读取管理员Classes数据\n文件关联/COM注册] O --> P2[后利用2: 篡改文件关联\n如.txt -> 恶意程序] O --> P3[后利用3: 植入恶意COM对象/Shell扩展\n管理员下次登录时以管理员身份执行] P2 --> Q[管理员登录时触发\n以管理员权限执行攻击者代码] P3 --> Q

5.3 各阶段详解

阶段一:环境准备与诱饵构造
攻击者在账户 A 下创建一个临时 DAT 文件(可以是任意合法 Hive 文件或空文件),并通过 ACL 设置使其对账户 B 不可完全访问(例如仅只读或完全拒绝)。该文件仅作为 CheckFullAccessOnFile 的“靶子”,目的是让检查必然失败,从而迫使 ProfSvc 走 SYSTEM 加载分支。

阶段二:符号链接与 Oplock 布设
攻击者构造路径操控链路:在用户可写的命名空间(如 \RPC Control)创建对象管理器符号链接,使其暂时指向诱饵 DAT。同时对诱饵 DAT 设置 Oplock,作为竞态同步点。

阶段三:触发 ProfSvc Hive 加载
攻击者使用账户 B 的凭据调用 CreateProcessAsUser(或等效的 RunAs 机制)创建进程。这会通知 ProfSvc 为账户 B 加载配置文件 Hive。攻击者需要让 ProfSvc 解析的 Hive 路径经过其布设的符号链接。

阶段四:竞态触发与路径替换
ProfSvc 在 CheckFullAccessOnFile 中打开诱饵 DAT,Oplock 命中,ProfSvc 阻塞。攻击者检测到 Oplock 命中后,原子性地将符号链接目标从诱饵 DAT 替换为账户 C(管理员)的 UsrClass.dat,随后释放 Oplock。

阶段五:Hive 劫持与挂载
ProfSvc 的 CheckFullAccessOnFile 返回“无完全访问权限”,进入 NtLoadKeyEx 分支。但此时路径已指向账户 C 的 UsrClass.dat,ProfSvc 以 SYSTEM 身份打开该文件(绕过其 ACL),并将 Hive 挂载到攻击者账户 A 的 HKEY_CLASSES_ROOT 空间下,且具备读写权限。

阶段六:后利用
攻击者现在可以读写管理员的 Classes Hive:

  • 数据窃取:读取管理员存储的文件关联、COM 注册、应用配置等敏感信息。
  • 文件关联劫持:将 .txt 等扩展名的关联程序改为攻击者控制的恶意程序。当管理员登录并打开此类文件时,恶意程序以管理员身份执行。
  • COM 对象 / Shell 扩展植入:覆盖管理员登录时自动加载的 COM 对象或 Shell 扩展注册,实现持久化与登录即执行。由于代码在合法管理员会话上下文中运行,对 EDR 而言看起来像正常活动,检测难度高。

研究员 Will Dormann 的演示印证了这一点:非管理员用户运行 LegacyHive 后,传入第二个标准用户凭据并指定管理员账户名,随后以该标准用户身份启动 regedit.exe,即可直接浏览并修改管理员的 Classes 注册表配置单元——包括把 .txt 关联从文本编辑器改为 calc.exe 作为概念验证。

六、PoC 概念代码

下面给出展示核心利用逻辑的 C/C++ 伪代码。该代码仅为概念演示,省略了错误处理与具体偏移,重点呈现符号链接构造、Oplock 同步与竞态触发的编排逻辑。

6.1 符号链接与 Oplock 基础设施

// ============ Object Manager 符号链接与 Oplock 工具(概念伪代码)============
#include <windows.h>
#include <winternl.h>

// 动态解析未文档化的 NT API
typedef NTSTATUS (NTAPI* _NtCreateSymbolicLinkObject)(
    PHANDLE LinkHandle, ACCESS_MASK DesiredAccess,
    POBJECT_ATTRIBUTES ObjectAttributes, PUNICODE_STRING LinkTarget);

_NtCreateSymbolicLinkObject NtCreateSymbolicLinkObject;

// 在对象管理器命名空间创建符号链接
HANDLE CreateObjectSymlink(LPCWSTR linkDir, LPCWSTR linkName, LPCWSTR target) {
    WCHAR fullPath[MAX_PATH];
    wsprintfW(fullPath, L"\\%s\\%s", linkDir, linkName);

    UNICODE_STRING objName;
    RtlInitUnicodeString(&objName, fullPath);
    OBJECT_ATTRIBUTES oa;
    InitializeObjectAttributes(&oa, &objName, OBJ_CASE_INSENSITIVE, NULL, NULL);

    UNICODE_STRING targetUs;
    RtlInitUnicodeString(&targetUs, target);

    HANDLE hLink = NULL;
    NtCreateSymbolicLinkObject(&hLink, SYMBOLIC_LINK_ALL_ACCESS, &oa, &targetUs);
    return hLink;
}

// 对文件设置机会锁(OVERLAPPED + OPLOCK)
HANDLE SetOplockOnFile(LPCWSTR filePath) {
    HANDLE hFile = CreateFileW(filePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
                               NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
    // 调用 DeviceIoControl with FSCTL_REQUEST_OPLOCK
    // 简化:返回文件句柄,实际需 RequestOplock 并等待完成
    return hFile;
}

6.2 竞态触发主循环

// ============ LegacyHive 竞态触发主逻辑(概念伪代码)============
void ExploitLegacyHive(LPCWSTR baitFile,      // 攻击者种植的诱饵DAT
                       LPCWSTR linkDir,        // 可写对象目录, 如 \RPC Control
                       LPCWSTR linkName,       // 符号链接名
                       LPCWSTR targetHive,     // 目标管理员UsrClass.dat全路径
                       LPCWSTR userBcreds,     // 第二标准用户凭据
                       LPCWSTR targetUserC) {  // 目标管理员账户名
    // 1. 布设符号链接: linkName -> 诱饵DAT(临时指向)
    HANDLE hLink = CreateObjectSymlink(linkDir, linkName, baitFile);

    // 2. 对诱饵DAT设置Oplock,作为竞态同步点
    HANDLE hOplock = SetOplockOnFile(baitFile);

    // 3. 启动监听线程:Oplock命中后替换符号链接目标
    HANDLE hSwapper = CreateThread(NULL, 0, [](LPVOID p)->DWORD {
        auto* args = (SwapArgs*)p;
        WaitForOplockBreak(args->hOplock);   // 阻塞直到ProfSvc打开诱饵DAT
        // 竞态窗口已打开:删除旧链接,创建指向目标的新链接
        NtClose(args->hLink);
        CreateObjectSymlink(args->linkDir, args->linkName, args->targetHive);
        ReleaseOplock(args->hOplock);        // 放行ProfSvc
        return 0;
    }, &swapArgs, 0, NULL);

    // 4. 以账户B身份创建进程,触发ProfSvc加载账户B的配置文件Hive
    //    ProfSvc将解析经过符号链接的Hive路径
    CreateProcessAsUserWithCreds(userBcreds, /* trigger profile load */);

    // 5. 等待竞态完成
    WaitForSingleObject(hSwapper, INFINITE);

    // 6. 此时账户C的UsrClass.dat已挂载到攻击者HKEY_CLASSES_ROOT
    //    攻击者可读写目标Classes Hive
    HKEY hTargetClasses;
    RegOpenKeyEx(HKEY_CLASSES_ROOT, L".txt", 0, KEY_SET_VALUE, &hTargetClasses);
    // 后利用示例:篡改文件关联
    RegSetValueEx(hTargetClasses, nullptr, 0, REG_SZ,
                  (BYTE*)L"malicious_handler", sizeof(L"malicious_handler"));
}

上述代码刻意简化了实际工程细节(如触发 ProfSvc 加载账户 B Hive 的精确机制、Oplock 的 FSCTL_REQUEST_OPLOCK 完整调用、连接点桥接等),但其准确表达了 LegacyHive 的三要素:符号链接布设 → Oplock 同步竞态 → 路径原子替换

七、0patch 微补丁技术原理

在微软尚未发布官方补丁的情况下,ACROS Security(0patch 团队)于 2026 年 7 月 20 日发布了免费微补丁。其技术原理值得深入分析,因为它精准地揭示了漏洞的修复思路。

7.1 微补丁逻辑

0patch 的修复策略是“软化”漏洞代码中的第二个检查分支,使最终逻辑变为:

  1. 存在用户令牌时,必须使用 NtLoadKey3 带模拟加载;只有无令牌(服务自身调用)的情况才走 NtLoadKeyEx(SYSTEM 身份)。这恢复了原始程序员设想的保护。
  2. CheckFullAccessOnFile 成功时:用 NtLoadKey3 模拟用户身份加载为完全访问 Hive(行为不变)。
  3. CheckFullAccessOnFile 失败时:仍用 NtLoadKey3 模拟用户身份加载,但作为只读 Hive(而非退回 SYSTEM 身份的 NtLoadKeyEx)。

关键变化在第 3 点:原来检查失败会以 SYSTEM 完全访问加载,现在改为以用户身份只读加载。这一改动同时满足两个目标:

  • 阻断攻击:攻击者的诱饵文件使检查失败后,Hive 只以用户身份只读加载。即便符号链接已指向目标 UsrClass.dat,也因模拟用户身份而受限于用户对该文件的 ACL(标准用户无权访问管理员 Hive),且只读无法写入——攻击失去意义。0patch 验证显示,开启补丁后攻击者加载到的是临时用户配置文件 Hive,而非管理员的 Hive。
  • 兼容合法场景:Mandatory User Profile(NTUSER.MAN 只读)场景仍可工作——只读加载本就是该场景所需。

7.2 微补丁覆盖范围

0patch 微补丁覆盖:

  • 受官方支持的版本:Windows 11 25H2/24H2/23H2、Windows Server 2025/2022(均已更新至 2026 年 7 月)。
  • 0patch 安全接管的版本:Windows 11 22H2/21H2、Windows 10 22H2/21H2/21H1/20H2/2004。

并明确指出该漏洞不影响 Windows 10 2004 之前的版本(含 Windows 7),也不影响 Windows Server 2008 R2 / 2012 / 2012 R2 / 2016 / 2019——因为漏洞代码分支在这些旧版本中尚不存在。

由于是 0day,该微补丁纳入 FREE 计划,直至微软官方补丁发布。

7.3 微补丁与官方补丁的工程对比

0patch 的修复凸显了一个重要的工程启示:安全检查的失败分支绝不能静默提升权限。原代码中“检查失败就以更高权限重试”的模式,从设计上就是反安全的——它把访问控制从“门禁”变成了“安检失败的 VIP 通道”。微补丁通过将失败分支降级为只读,在不破坏功能的前提下消除了权限提升路径,体现了最小权限原则的正确应用。

八、检测规则

在无补丁环境下,检测是第一道防线。LegacyHive 的检测应聚焦行为特征而非签名(PoC 可重命名重构)。

8.1 Sysmon 检测规则

规则一:ProfSvc 托管进程异常 Hive 加载(Event ID 12/13 注册表对象事件)

监控 svchost.exe(ProfSvc 宿主)加载非当前登录用户 Hive 的行为:

<!-- Sysmon 配置:监控 NtLoadKey 加载注册表 Hive -->
<RuleGroup name="Registry Hive Load" groupRelation="or">
  <RegistryEvent onmatch="include">
    <!-- Event ID 12: 注册表键/值创建与删除 -->
    <!-- 捕获 HKEY_USERS 下非交互登录用户的 Hive 挂载 -->
    <TargetObject condition="contains">\REGISTRY\USER\S-</TargetObject>
    <EventType condition="is">CreateKey</EventType>
  </RegistryEvent>
</RuleGroup>

规则二:标准用户进程创建对象管理器符号链接与重解析点(Event ID 1 进程创建 + 文件事件)

监控低权限进程在受限命名空间创建符号链接、连接点的行为,特别是临近 ProfSvc 操作时:

<RuleGroup name="Suspicious Symlink/Junction Creation" groupRelation="or">
  <FileCreate onmatch="include">
    <TargetFilename condition="contains">\RPC Control\</TargetFilename>
    <TargetFilename condition="contains">\BaseNamedObjects\Restricted\</TargetFilename>
  </FileCreate>
  <ProcessCreate onmatch="include">
    <!-- 捕获携带 CreateProcessAsUser + 符号链接工具调用的可疑进程链 -->
    <Image condition="end with">\LegacyHive.exe</Image>
    <CommandLine condition="contains">/user:</CommandLine>
    <ParentImage condition="end with">\cmd.exe</ParentImage>
  </ProcessCreate>
</RuleGroup>

规则三:跨账户 Hive 文件访问(Event ID 11 文件创建 + Event ID 10 文件访问)

监控一个用户进程访问另一用户配置文件目录下 UsrClass.dat / NTUSER.DAT 的行为:

<RuleGroup name="Cross-User Hive Access" groupRelation="or">
  <FileCreate onmatch="include">
    <TargetFilename condition="contains">UsrClass.dat</TargetFilename>
    <TargetFilename condition="contains">NTUSER.DAT</TargetFilename>
  </FileCreate>
</RuleGroup>

8.2 进程监控(Process Monitor)特征

用 Sysinternals Process Monitor 可观察到 LegacyHive 的典型行为指纹:

  1. 首次以低权限身份打开目标管理员 UsrClass.dat 返回 ACCESS DENIED
  2. 紧接着以 NT AUTHORITY\SYSTEM 上下文重试打开同一文件并成功
  3. 随后该 Hive 被挂载,攻击者账户可访问其内容。

这一“先拒后成”的模式(ACCESS DENIED → SYSTEM 重试成功)是 LegacyHive 的强特征,与 Project Zero 早年记录的任意文件创建与 Classes Hive 劫持模式一脉相承。

8.3 EDR / SIEM 关联规则

在 SIEM 中建议建立以下关联检测:

  • 规则 A:同一标准用户进程在短时间内(如 5 秒内)同时出现“对象管理器符号链接创建 + CreateProcessAsUser 调用 + 注册表 Hive 挂载事件”三连,判定为高危。
  • 规则 Bsvchost.exe(ProfSvc)加载的 Hive 路径不属于当前交互登录用户的配置文件目录,触发告警。
  • 规则 C:标准用户进程访问 C:\Users\<其他用户>\AppData\Local\Microsoft\Windows\UsrClass.dat,触发告警。
  • 规则 D:监控 Local AppData 注册表值被修改指向非标准配置文件目录的行为(攻击链的路径操控前置步骤)。

由于竞态型利用往往多次失败后才成功,应关注失败尝试的聚类而非单次事件。

九、缓解措施

在官方补丁发布前,建议采取分层缓解:

9.1 首选:部署 0patch 微补丁

对受影响系统部署 0patch FREE 计划中的 LegacyHive 微补丁,这是当前唯一可用的针对性修复。微补丁无需重启、可即时生效,且在微软官方补丁发布后可平滑替换。

9.2 限制特权账户本地登录

  • 禁止管理员账户在共享/低信任系统上交互登录,遵循管理账号与日常使用账号分离原则。
  • 对管理员账户配置“拒绝本地登录”组策略,仅允许通过受管跳板机访问。
  • 避免在共享工作站上保留已登录的特权会话。

9.3 应用控制

部署 WDAC(Windows Defender Application Control)或 AppLocker,阻止标准用户执行未签名/未批准的二进制文件、脚本及用户可写路径下的启动项。这直接抬高了攻击者“在本地获得代码执行”的第一道门槛——LegacyHive 本身需要攻击者已能运行代码。

9.4 注册表与文件权限加固

  • 审计并收紧用户配置文件目录的 ACL,确保标准用户无法枚举其他用户的 NTUSER.DAT / UsrClass.dat 路径。
  • 监控 HKEY_USERS 下非预期 SID 的 Hive 挂载。

9.5 多用户环境专项加固

对 RDS Host、共享桌面、教室机房等高暴露环境:

  • 强制使用 Mandatory Profile 或 FCU(强制用户配置文件)以减少可写 Hive 暴露面。
  • 启用会话隔离与用户配置文件磁盘(UPD)。
  • 缩短空闲会话超时,减少竞态触发窗口。

十、与历史类似漏洞的对比

LegacyHive 并非孤立事件,它延续了一条清晰的 Windows 符号链接提权技术脉络。

10.1 CVE-2021-26868:图形组件符号链接提权

CVE-2021-26868 是 Windows 图形组件的本地提权漏洞,其利用同样依赖符号链接/连接点重定向高权限服务的文件访问。攻击者通过在用户可写位置布置连接点,使图形子系统以 SYSTEM 身份打开被重定向的目标文件,从而实现权限提升。微软的修复方向是路径规范化与重解析点感知——这与 SOC Prime 对 LegacyHive 建议的修复思路(路径规范化、拒绝 Object Manager 命名空间前缀)一致。

10.2 James Forshaw 的符号链接研究体系

Google Project Zero 研究员 James Forshaw 在 2015 年发表的 “A Link to the Past: Abusing Symbolic Links on Windows” 奠定了这一领域的方法论。他系统梳理了三类可被滥用的符号链接(NTFS 符号链接、连接点、对象管理器符号链接)以及配套的竞态技术(oplock、BaitAndSwitch)。LegacyHive 的 Oplock + 对象管理器符号链接组合,正是 Forshaw 工具链(如 BaitAndSwitchCreateDosDeviceSymlinkCreateMountPoint)的标准运用。

Forshaw 同时推动了微软的“符号链接加固(symlink hardening)”工程——通过 FILE_FLAG_OPEN_REPARSE_POINT、重解析点感知的路径解析等机制减少此类攻击面。然而 LegacyHive 证明,只要系统服务中仍存在“用户可影响路径 + 高权限代理访问 + 检查/使用时间差”的组合,这类攻击就难以根除。

10.3 itm4n 的 Classes Hive 劫持与 PPLdump

研究员 itm4n(Clement Labro)实现的 PPLdump 工具利用 DefineDosDevice + \?? 符号链接链,将伪造的 Section 对象植入 \KnownDlls,绕过 PPL(Protected Process Light)保护转储 LSASS。其技术内核——对象管理器符号链接重定向特权进程的资源解析——与 LegacyHive 的路径操控如出一辙。itm4n 同时记录了 Classes Hive 劫持的利用模式,LegacyHive 可视为该模式在 ProfSvc 场景的再实现。

10.4 同一研究员的 BlueHammer

值得特别注意的是,LegacyHive 的作者 Nightmare-Eclipse 此前还公开了 BlueHammer 漏洞利用,针对 Windows Defender(MsMpEng.exe,SYSTEM 权限)。BlueHammer 同样采用对象管理器符号链接重定向技术:通过连接点把 Defender 更新目录重定向到 \BaseNamedObjects\Restricted,再用 NtCreateSymbolicLinkObject 在该受限空间创建指向 VSS(卷影副本)中 SAM Hive 的符号链接,诱使 Defender 以 SYSTEM 身份打开 SAM Hive。两个漏洞共享同一套路径操控工具链,差别仅在被劫持的高权限服务(ProfSvc vs Defender)与目标资源(用户 Hive vs SAM Hive)。这表明该研究员系统性地掌握了“对象管理器符号链接 + oplock 竞态”这一攻击范式,并能灵活迁移到不同服务。

10.5 对比总结表

维度 LegacyHive CVE-2021-26868 BlueHammer itm4n Classes Hive 劫持
受害服务 ProfSvc(SYSTEM) 图形组件 Defender MsMpEng(SYSTEM) 各类特权服务
路径操控 OM符号链接+连接点 连接点 OM符号链接+连接点 DosDevice+符号链接
竞态同步 Oplock Oplock Oplock+Cloud Files API Oplock
目标资源 用户UsrClass.dat 文件/注册表 SAM Hive(VSS) Classes Hive
提权结果 读写管理员Hive SYSTEM文件操作 读取SAM 读写目标Hive
修复方向 路径规范化+降级加载 路径规范化 路径校验 重解析点感知

十一、技术启示与展望

LegacyHive 的价值不仅在于其作为未修补 0day 的即时威胁,更在于它揭示了 Windows 配置文件管理代码深层的信任模型缺陷。

启示一:检查失败不应提升权限。 漏洞代码“访问检查失败则以更高权限重试”的设计,从根本上违背了最小权限原则。任何安全检查的失败分支都应当降级拒绝,而非静默提权。0patch 微补丁正是通过将失败分支降级为只读,以最小改动消除了漏洞。

启示二:用户可影响路径 + 高权限代理 = 永恒攻击面。 只要系统服务继续以 SYSTEM 身份处理用户可影响的路径(配置文件路径、更新路径、临时目录),并存在检查与使用的时间差,符号链接提权就持续有效。Forshaw 的研究已过去十年,微软的符号链接加固也持续推进,但 LegacyHive 与 BlueHammer 证明这一攻击范式依然生命力旺盛。架构层面的修复——如让特权服务在用户安全上下文下执行用户相关 I/O、对用户提供的路径进行规范化和边界校验、拒绝 Object Manager 命名空间前缀——才是治本之道。

启示三:竞态型利用的检测应关注聚类而非单点。 Oplock 同步使竞态利用高度可靠,但攻击者仍可能多次尝试。检测规则应聚焦行为序列的聚类(符号链接创建 + RunAs + Hive 加载的时序组合)与跨账户资源访问异常,而非依赖单一特征。

启示四:无 CVE 不等于无风险。 LegacyHive 在披露时无 CVE、无官方补丁,导致依赖 CVE 驱动的资产扫描与漏洞管理流程出现盲区。安全团队需要建立基于漏洞名称、受影响组件与行为特征的跟踪能力,而非仅依赖 CVE 编号。

启示五:研究员的“刻意限制”降低了即时威胁但不应降低重视。 CrowdStrike 确认公开 PoC 被刻意限制(需第二用户凭据、仅限 UsrClass.dat)。这延缓了武器化,但研究员声称完整版可免凭据加载任意 Hive。防御者应按“完整版能力”评估风险并加固,而非仅针对公开 PoC 的限制版本做防御。

随着微软持续调查并最终发布官方补丁,LegacyHive 的技术细节将成为 Windows 提权研究的重要案例。它再次提醒我们:在操作系统这一复杂系统中,配置文件管理、命名空间解析与特权服务执行三者的交汇处,永远是攻击者与防御者博弈的前沿。


参考资料:

  • 0patch 官方博客:《Free micropatches available for "LegacyHive" 0day》(Mitja Kolsek,2026-07-20)
  • SOC Prime 技术分析:《LegacyHive: The Windows User Profile Service Bug That Loads Another User's Registry Hive》
  • SecurityWeek:《Nightmare Eclipse Drops 'LegacyHive' Windows Zero-Day》
  • WindowsForum:《LegacyHive Windows ProfSvc Zero-Day: Detect and Contain LPE》
  • FreeBuf:《Windows LegacyHive 0Day 漏洞可让黑客获取管理员权限》
  • James Forshaw(Google Project Zero):《A Link to the Past: Abusing Symbolic Links on Windows》(2015)
  • itm4n(Clement Labro):PPLdump 与 Classes Hive 劫持研究
  • Nightmare-Eclipse GitHub:LegacyHive / BlueHammer PoC 仓库
  • MITRE CWE-362:Race Condition