一、前言
在 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 进程会验证凭据并创建一个初始令牌,此后该用户启动的所有进程都会继承这个令牌。
一个令牌主要包含以下三部分核心信息:
- 用户 SID(Security Identifier): 标识你是谁。
- 组 SIDs: 标识你属于哪个组织(如 Administrators 组)。
- 特权列表(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)是指用户或进程被授权执行特定系统操作的权限。通过滥用这些特权,攻击者可以提升自身权限,获取更高的系统访问权限。
可被进一步利用的特权包括:
- SeImpersonatePrivilege:允许模拟其他用户的令牌。
- SeAssignPrimaryPrivilege:允许为进程分配主令牌。
- SeTcbPrivilege:提供接近SYSTEM级别的控制能力。
- SeBackupPrivilege:允许备份系统文件。
- SeRestorePrivilege:允许恢复系统文件。
- SeCreateTokenPrivilege:允许创建新的令牌。
- SeLoadDriverPrivilege:允许加载驱动程序。
- SeTakeOwnershipPrivilege:允许接管文件或对象的所有权。
- 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)。
- 步骤:
- 使用Juicy Potato触发NTLM认证,捕获SYSTEM令牌。
- 利用捕获的令牌创建新进程,获得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提权。 - 步骤:
- 获取SYSTEM令牌。
- 调用
CreateProcessAsUser,传入SYSTEM令牌,创建高权限进程。
4.3 SeTcbPrivilege
拥有此特权的用户:
- 极少数高权限账户(如SYSTEM)
利用原理:
SeTcbPrivilege是Windows中最强大的特权之一,该特权代表你是“操作系统的一部分”。拥有此特权可以直接调用 LsaLogonUser 伪造任何用户的令牌,并直接将其加入 Local System 组。
利用场景:
- 步骤:
- 使用
LsaLogonUser创建令牌。 - 将令牌添加到Local System组。
- 使用令牌执行高权限操作。
- 使用
- 参考代码:https://github.com/3gstudent/Homework-of-C-Language/blob/master/EnableSeTcbPrivilege.cpp
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创建高权限令牌,并将其添加到管理员组。
利用场景:
- 步骤:
- 使用
ZwCreateToken创建Primary Token。 - 将令牌添加到Local Administrator组。
- 使用令牌执行高权限操作。
- 使用
4.7 SeLoadDriverPrivilege
拥有此特权的用户:
- 管理员
- 部分服务账户
利用原理:
SeLoadDriverPrivilege允许用户动态加载内核驱动。攻击者可加载存在漏洞的驱动程序(如Capcom.sys)来提权。
利用场景:
- 工具:Metasploit的
capcom_sys_exec模块。 - 步骤:
- 加载Capcom.sys驱动。
- 利用驱动漏洞执行提权代码。
- 参考代码:https://github.com/tandasat/ExploitCapcom
4.8 SeTakeOwnershipPrivilege
拥有此特权的用户:
- 管理员
利用原理:
SeTakeOwnershipPrivilege允许用户接管系统任意文件的所有权,与SeRestorePrivilege类似,可用于修改关键文件。
利用场景:
- 接管系统文件后,结合其他漏洞提权。
4.9 SeDebugPrivilege
拥有此特权的用户:
- 管理员
- 部分服务账户
这被认为是 Windows 中最危险的特权,因为它赋予了用户“上帝视角”。
- 底层逻辑: 该特权设计初衷是让开发人员调试进程。开启后,它可以绕过所有的对象权限检查,允许调用
OpenProcess获取任何进程(包括lsass.exe或winlogon.exe)的句柄。 - 利用路径:
- 开启特权。
- 找到 SYSTEM 进程(如 PID 极低的系统服务)。
- 使用
VirtualAllocEx和WriteProcessMemory在该进程中注入 Shellcode。 - 通过
CreateRemoteThread执行。
五、 特权利用的进阶:令牌窃取与重定向
提权的本质往往不是“创造”权限,而是“借用”权限。
5.1 令牌模拟(Impersonation) vs 令牌克隆(Primary Token)
- 模拟(Level 3): 仅能用于网络访问或简单的资源访问。
- 授权(Level 4 / Delegation): 允许你像该用户一样在本地和网络上为所欲为。
攻击者通过
DuplicateTokenEx将一个“模拟令牌”提升为“主令牌”,这样才能绕过 UAC 或启动全新的交互式 Shell。
5.2 令牌获取的常见路径
- 进程注入: 注入到拥有目标令牌的进程。
- 命名管道劫持: 强制高权限进程连接恶意管道。
- 中间人中继(Relay): 强制系统执行 NTLM 认证。
六、 总结
Windows 令牌特权提权是一场关于“系统规则滥用”的游戏。每一个特权的背后,都对应着一个原本为了系统维护而设计的便捷功能,但在权限配置不当的情况下,它们便成了攻击者的阶梯。
掌握这些特权,不仅要求我们要会使用 Potato 脚本,更要求我们理解 Windows 安全参考监视器(SRM)的决策过程。在这个层面上,安全研究不再是寻找代码漏洞,而是寻找逻辑缺陷和配置疏漏。
原文 https://blog.csdn.net/2301_79518550/article/details/145807536