以最复杂方式绕过UAC
虽然我不常研究这个,但发现新的UAC绕过方法总是很有趣。在阅读Rubeus工具的功能时,我意识到可以滥用Kerberos协议绕过UAC——至少在域加入系统中可行。不清楚之前是否有人记录过这种方法,有篇帖子讨论过类似技术但需要从其他系统发起攻击,而本文将描述本地实现的方案。
技术背景
系统默认会通过LSASS过滤网络身份验证令牌,移除本地管理员的权限。但存在关键例外:如果用户是域用户兼本地管理员,LSASS会允许网络认证使用完整管理员令牌。这在通过Kerberos进行本地认证时会产生问题——难道这不是简单的UAC绕过吗?
实际上Kerberos有专门机制阻止这种攻击。去年我阅读了微软工程师Steve Syfuhs关于Kerberos如何防止本地UAC绕过的文章。简而言之:当用户请求服务票据时,LSASS会在TGS-REQ请求中嵌入本地安全信息,这些信息会被编码到生成的票据中。当该票据用于本地系统认证时,Kerberos会提取这些信息进行验证。
通过分析Kerberos票据,我们发现两个关键字段:
|
|
核心绕过机制
LSASS通过LsaISetSupplementalTokenInfo
函数处理这些字段,主要检查包括:
- 比较票据中的MachineID与LSASS内存中的值
- 检查未公开的LSA网络令牌过滤标志
- 验证用户SID是否属于本地账户域
当满足以下任一条件时过滤将失效:
- 用户SID不属于本地账户域
- LocalAccountTokenFilterPolicy策略非零
- 系统是域控制器(NtProductLanManNt)
两种具体利用方法
方法一:票据重用攻击
- 获取本地系统的服务票据并保存
- 重启系统使LSASS重新初始化
- 重新加载旧票据,此时MachineID不匹配导致过滤失效
|
|
方法二:票据伪造攻击
- 利用Benjamin Delpy在kekeo中发现的非约束委派漏洞获取本地TGT
- 向KDC请求新的本地服务票据,填充伪造的MachineID
- 将伪造票据导入缓存实现UAC绕过
KERB-LOCAL的奥秘
这个字段设计用于凭证重用,但实际使用频率很低,因为:
- 仅当服务端使用Negotiate包时有效
- 本地Negotiate认证默认会选择NTLM协议
有趣的是,KERB-LOCAL中的值实际是LSASS堆中KERB_CREDENTIAL结构的地址和票据计数。虽然Kerberos会验证PAC中的SID匹配性,但这种实现方式可能存在安全隐患。
[更新] 文末提供了修改Win32 SCM API以强制使用Kerberos本地认证的C++代码示例。