// 红队渗透 · 2025-02-27

Windows 令牌特权(Token Privileges)的底层原理与提权实战

一、前言

在 Windows 渗透测试的漫长链路中,权限提升(Privilege Escalation)是决定成败的关键一步。许多初学者能熟练使用 getsystem 或 juicypotato.exe,但往往对其背后的深层机制——访问令牌(Access Token)与系统特权(Privileges)——缺乏系统性认知。

Windows 的安全模型并非简单的“非黑即白”,而是一套复杂的权限叠加体系。本文将跳出工具使用的表面逻辑,带你深入 Windows 内核安全架构,探讨那些隐藏在令牌中的“幽灵钥匙”是如何被攻击者利用,从而实现从普通用户到系统最高权限(SYSTEM)的华丽转身。

本文参考了GitHub上的《Priv2Admin》项目(https://github.com/gtworek/Priv2Admin)以及其他相关资料。


二、Windows 访问控制架构

安全参考监视器(SRM)

Windows 内核中的安全参考监视器(Security Reference Monitor, SRM)是所有权限检查的终点。无论是访问文件、结束进程还是更改系统时间,请求都会经过 SRM 的裁定。而 SRM 裁定的依据主要有两个:

  • 对象的 ACL(访问控制列表): 决定了对象允许谁进入。

  • 主体的访问令牌(Access Token): 决定了请求者的身份和拥有的特殊权力。

什么是访问令牌(Access Token)?

访问令牌是 Windows 安全子系统的核心对象,它像是一张“动态电子身份证”。每当一个用户登录时,lsass.exe 进程会验证凭据并创建一个初始令牌,此后该用户启动的所有进程都会继承这个令牌。

一个令牌主要包含以下三部分核心信息:

  1. 用户 SID(Security Identifier): 标识你是谁。
  2. 组 SIDs: 标识你属于哪个组织(如 Administrators 组)。
  3. 特权列表(Privileges): 标识你能跨越安全规则执行哪些操作。

特权(Privilege)与权限(Permission)的区别

这是最容易混淆的概念。

  • 权限(Permission/ACL): 属于对象(Object)。例如,一个文件、一个注册表键值。它决定了“谁能对这个特定文件进行读写”。
  • 特权(Privilege): 属于令牌(Token)。它是系统级别的。它决定了“这个令牌持有者能否执行某些影响整个系统的操作”,例如重启系统、加载驱动、调试其他进程。

关键点: 特权具有“越级性”。例如,即使一个文件在 ACL 权限上禁止你读取,但如果你拥有 SeBackupPrivilege 特权,你可以绕过文件系统的所有权限检查强行读取。这就是提权的逻辑基石。


三、权限状态的意义

在执行 whoami /priv 时,你会发现大部分特权的状态是 Disabled。这常常让初学者产生误解。

状态分类

  • Enabled: 该特权已启用,程序可以直接调用关联的敏感 API。
  • Disabled: 该特权存在于令牌中,但当前未开启。这不代表你没有这个权限。 只要它出现在列表里,就意味着该用户“拥有”激活它的权利。
  • Removed: 特权已从令牌中永久移除,除非重新登录或获取新令牌,否则无法恢复。

Disabled状态的含义

  • 对用户的影响:禁用状态并不意味着用户无法使用该特权。只要特权出现在用户的令牌中,用户就拥有该特权,系统会在需要时自动启用。例如,SeShutdownPrivilege为禁用状态时,用户仍可通过shutdown命令关闭系统。
  • 对程序的影响:禁用状态主要限制程序直接调用相关Windows API。例如,程序若需使用SeShutdownPrivilege关闭系统,必须先调用AdjustTokenPrivileges将特权状态改为“Enabled”。

为什么存在禁用状态?

禁用状态的目的是增强系统安全性,防止程序滥用特权。例如,未经授权的程序无法直接调用特权相关的API,从而降低恶意代码的风险。

如何启用特权?

要将特权状态从“Disabled”改为“Enabled”,可以使用以下代码示例(参考EnablePrivilegeandGetTokenInformation.cpp):

#include <windows.h>
#include <stdio.h>

BOOL EnablePrivilege(LPCTSTR PrivilegeName) {
    HANDLE hToken;
    TOKEN_PRIVILEGES tp;
    BOOL status;
    DWORD error;

    // 打开当前进程的令牌
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
        error = GetLastError();
        printf("OpenProcessToken failed: %d\n", error);
        return FALSE;
    }

    // 设置特权
    tp.PrivilegeCount = 1;
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!LookupPrivilegeValue(NULL, PrivilegeName, &tp.Privileges[0].Luid)) {
        error = GetLastError();
        printf("LookupPrivilegeValue failed: %d\n", error);
        CloseHandle(hToken);
        return FALSE;
    }

    // 调整令牌特权
    status = AdjustTokenPrivileges(hToken, FALSE, &tp, 0, NULL, NULL);
    error = GetLastError();
    CloseHandle(hToken);

    if (!status || (error != ERROR_SUCCESS)) {
        printf("AdjustTokenPrivileges failed: %d\n", error);
        return FALSE;
    }

    return TRUE;
}

int main() {
    if (EnablePrivilege(SE_SHUTDOWN_NAME)) {
        printf("Successfully enabled SeShutdownPrivilege\n");
    } else {
        printf("Failed to enable SeShutdownPrivilege\n");
    }
    return 0;
}

这段代码展示了如何启用SeShutdownPrivilege,其他特权的启用方式类似。


四、九大高危特权利用详解

前面我们说过,特权(Privilege)是指用户或进程被授权执行特定系统操作的权限。通过滥用这些特权,攻击者可以提升自身权限,获取更高的系统访问权限。

可被进一步利用的特权包括:

  1. SeImpersonatePrivilege:允许模拟其他用户的令牌。
  2. SeAssignPrimaryPrivilege:允许为进程分配主令牌。
  3. SeTcbPrivilege:提供接近SYSTEM级别的控制能力。
  4. SeBackupPrivilege:允许备份系统文件。
  5. SeRestorePrivilege:允许恢复系统文件。
  6. SeCreateTokenPrivilege:允许创建新的令牌。
  7. SeLoadDriverPrivilege:允许加载驱动程序。
  8. SeTakeOwnershipPrivilege:允许接管文件或对象的所有权。
  9. SeDebugPrivilege:允许调试进程,包括读写内存。

以下用户类型通常拥有这些特权:

  • IIS或SQL Server用户:常具有SeImpersonatePrivilege和SeAssignPrimaryPrivilege。
  • Backup Service用户:通常具有SeBackupPrivilege和SeRestorePrivilege。
  • 管理员账户:可能拥有上述大部分特权,但具体取决于系统配置。

以下是对九种特权的具体利用方法。

4.1 SeImpersonatePrivilege

拥有此特权的用户:

  • 管理员账户
  • 本地服务账户
  • 服务控制管理器(SCM)启动的服务
  • 配置为特定账户运行的COM服务器
  • IIS和SQL Server用户

利用原理: SeImpersonatePrivilege允许允许程序模拟其他客户端的令牌。如果攻击者能诱骗一个 SYSTEM 权限的服务(如通过 BITS 服务或打印机服务)来连接攻击者控制的命名管道,攻击者就可以“截获”并“套用”这个 SYSTEM 令牌。常见利用方式是通过NTLM Relay或本地协商获取SYSTEM令牌,然后使用该令牌执行高权限操作。

利用场景:

Juicy Potato / GodPotato: 通过强制 COM 服务器在本机特定端口进行认证,拦截 NTLM 认证过程,从而获取 SYSTEM 级别的模拟令牌。

  • 场景:攻击者获得IIS或SQL Server用户的权限。
  • 工具:Juicy Potato(https://github.com/ohpe/juicy-potato)。
  • 步骤:
    1. 使用Juicy Potato触发NTLM认证,捕获SYSTEM令牌。
    2. 利用捕获的令牌创建新进程,获得SYSTEM权限。
  • 示例命令:
    juicypotato.exe -l 1337 -p cmd.exe -t * -c {4991d34b-80a1-4291-83b6-3328366b9097}

4.2 SeAssignPrimaryPrivilege

拥有此特权的用户:

  • IIS和SQL Server用户

利用原理: SeAssignPrimaryPrivilege允许进程为其他进程分配主令牌。与SeImpersonatePrivilege类似,攻击者通过NTLM Relay获取SYSTEM令牌后,可使用CreateProcessAsUser创建新进程,赋予其SYSTEM权限。

攻防差异: SeImpersonate 主要是模拟已有的连接,而 SeAssignPrimary 允许你直接通过 CreateProcessAsUser 启动一个完全属于 SYSTEM 的新进程。

利用场景:

  • 与SeImpersonatePrivilege类似,使用Juicy Potato提权。
  • 步骤:
    1. 获取SYSTEM令牌。
    2. 调用CreateProcessAsUser,传入SYSTEM令牌,创建高权限进程。

4.3 SeTcbPrivilege

拥有此特权的用户:

  • 极少数高权限账户(如SYSTEM)

利用原理: SeTcbPrivilege是Windows中最强大的特权之一,该特权代表你是“操作系统的一部分”。拥有此特权可以直接调用 LsaLogonUser 伪造任何用户的令牌,并直接将其加入 Local System 组。

利用场景:

4.4 SeBackupPrivilege

拥有此特权的用户:

  • Backup Service
  • 管理员

利用原理: SeBackupPrivilege允许用户读取系统任意文件,包括敏感的注册表文件(如SAM、SYSTEM、SECURITY)。攻击者可利用此特权备份这些文件,并使用Mimikatz破解密码。

利用场景:

  • 绕过 ACL: 即使 C:\Windows\System32\config\SAM 对你显示“拒绝访问”,只要开启 SeBackupPrivilege,你在调用 CreateFile 时传入 FILE_FLAG_BACKUP_SEMANTICS 标志,内核就会直接放行。

  • 获取凭据: 备份 SAM 和 SYSTEM 注册表蜂窝文件,拖回本地解密,即可获取本地管理员的 NTLM Hash。

参考:https://cloud.tencent.com/developer/article/1672598

4.5 SeRestorePrivilege

拥有此特权的用户:

  • Backup Service
  • 管理员

利用原理: SeRestorePrivilege允许用户写入系统任意文件。攻击者可利用此特权修改关键系统文件,但需注意,在Windows 10及以上版本中,映像劫持等传统方法已失效。

利用场景:

  • 修改系统配置文件(如服务启动项),但需结合其他漏洞。

4.6 SeCreateTokenPrivilege

拥有此特权的用户:

  • 极少数账户(Win10中普通用户通常无此权限)

利用原理: SeCreateTokenPrivilege允许用户创建新的Windows令牌。攻击者可通过ZwCreateToken创建高权限令牌,并将其添加到管理员组。

利用场景:

  • 步骤:
    1. 使用ZwCreateToken创建Primary Token。
    2. 将令牌添加到Local Administrator组。
    3. 使用令牌执行高权限操作。

4.7 SeLoadDriverPrivilege

拥有此特权的用户:

  • 管理员
  • 部分服务账户

利用原理: SeLoadDriverPrivilege允许用户动态加载内核驱动。攻击者可加载存在漏洞的驱动程序(如Capcom.sys)来提权。

利用场景:

4.8 SeTakeOwnershipPrivilege

拥有此特权的用户:

  • 管理员

利用原理: SeTakeOwnershipPrivilege允许用户接管系统任意文件的所有权,与SeRestorePrivilege类似,可用于修改关键文件。

利用场景:

  • 接管系统文件后,结合其他漏洞提权。

4.9 SeDebugPrivilege

拥有此特权的用户:

  • 管理员
  • 部分服务账户

这被认为是 Windows 中最危险的特权,因为它赋予了用户“上帝视角”。

  • 底层逻辑: 该特权设计初衷是让开发人员调试进程。开启后,它可以绕过所有的对象权限检查,允许调用 OpenProcess 获取任何进程(包括 lsass.exe 或 winlogon.exe)的句柄。
  • 利用路径:
    1. 开启特权。
    2. 找到 SYSTEM 进程(如 PID 极低的系统服务)。
    3. 使用 VirtualAllocEx 和 WriteProcessMemory 在该进程中注入 Shellcode。
    4. 通过 CreateRemoteThread 执行。

五、 特权利用的进阶:令牌窃取与重定向

提权的本质往往不是“创造”权限,而是“借用”权限。

5.1 令牌模拟(Impersonation) vs 令牌克隆(Primary Token)

  • 模拟(Level 3): 仅能用于网络访问或简单的资源访问。
  • 授权(Level 4 / Delegation): 允许你像该用户一样在本地和网络上为所欲为。 攻击者通过 DuplicateTokenEx 将一个“模拟令牌”提升为“主令牌”,这样才能绕过 UAC 或启动全新的交互式 Shell。

5.2 令牌获取的常见路径

  1. 进程注入: 注入到拥有目标令牌的进程。
  2. 命名管道劫持: 强制高权限进程连接恶意管道。
  3. 中间人中继(Relay): 强制系统执行 NTLM 认证。

六、 总结

Windows 令牌特权提权是一场关于“系统规则滥用”的游戏。每一个特权的背后,都对应着一个原本为了系统维护而设计的便捷功能,但在权限配置不当的情况下,它们便成了攻击者的阶梯。

掌握这些特权,不仅要求我们要会使用 Potato 脚本,更要求我们理解 Windows 安全参考监视器(SRM)的决策过程。在这个层面上,安全研究不再是寻找代码漏洞,而是寻找逻辑缺陷和配置疏漏。

原文 https://blog.csdn.net/2301_79518550/article/details/145807536