以最复杂方式绕过UAC:Kerberos协议漏洞利用详解

本文深入剖析如何通过操纵Kerberos票据中的KERB-AD-RESTRICTION-ENTRY和KERB-LOCAL字段,在域环境中实现本地用户账户控制(UAC)绕过。文章详细解释了LSASS的令牌过滤机制及两种具体利用方法,涉及服务票据重用和伪造技术。

以最复杂方式绕过UAC

虽然我不常研究这个,但发现新的UAC绕过方法总是很有趣。在阅读Rubeus工具的功能时,我意识到可以滥用Kerberos协议绕过UAC——至少在域加入系统中可行。不清楚之前是否有人记录过这种方法,有篇帖子讨论过类似技术但需要从其他系统发起攻击,而本文将描述本地实现的方案。

技术背景

系统默认会通过LSASS过滤网络身份验证令牌,移除本地管理员的权限。但存在关键例外:如果用户是域用户兼本地管理员,LSASS会允许网络认证使用完整管理员令牌。这在通过Kerberos进行本地认证时会产生问题——难道这不是简单的UAC绕过吗?

实际上Kerberos有专门机制阻止这种攻击。去年我阅读了微软工程师Steve Syfuhs关于Kerberos如何防止本地UAC绕过的文章。简而言之:当用户请求服务票据时,LSASS会在TGS-REQ请求中嵌入本地安全信息,这些信息会被编码到生成的票据中。当该票据用于本地系统认证时,Kerberos会提取这些信息进行验证。

通过分析Kerberos票据,我们发现两个关键字段:

1
2
3
4
5
6
7
<Authorization Data - KERB_AD_RESTRICTION_ENTRY>
Flags           : LimitedToken
Integrity Level : Medium
Machine ID      : 6640665F...

<Authorization Data - KERB_LOCAL>
Security Context: 60CE03337E01000025FC763900000000

核心绕过机制

LSASS通过LsaISetSupplementalTokenInfo函数处理这些字段,主要检查包括:

  1. 比较票据中的MachineID与LSASS内存中的值
  2. 检查未公开的LSA网络令牌过滤标志
  3. 验证用户SID是否属于本地账户域

当满足以下任一条件时过滤将失效:

  • 用户SID不属于本地账户域
  • LocalAccountTokenFilterPolicy策略非零
  • 系统是域控制器(NtProductLanManNt)

两种具体利用方法

方法一:票据重用攻击

  1. 获取本地系统的服务票据并保存
  2. 重启系统使LSASS重新初始化
  3. 重新加载旧票据,此时MachineID不匹配导致过滤失效
1
2
3
4
PS> klist get RPC/$env:COMPUTERNAME
PS> Rubeus.exe /dump /server:$env:COMPUTERNAME /nowrap
# 保存Base64票据后重启
PS> Rubeus.exe ptt /ticket:<BASE64 TICKET>

方法二:票据伪造攻击

  1. 利用Benjamin Delpy在kekeo中发现的非约束委派漏洞获取本地TGT
  2. 向KDC请求新的本地服务票据,填充伪造的MachineID
  3. 将伪造票据导入缓存实现UAC绕过

KERB-LOCAL的奥秘

这个字段设计用于凭证重用,但实际使用频率很低,因为:

  1. 仅当服务端使用Negotiate包时有效
  2. 本地Negotiate认证默认会选择NTLM协议

有趣的是,KERB-LOCAL中的值实际是LSASS堆中KERB_CREDENTIAL结构的地址和票据计数。虽然Kerberos会验证PAC中的SID匹配性,但这种实现方式可能存在安全隐患。

[更新] 文末提供了修改Win32 SCM API以强制使用Kerberos本地认证的C++代码示例。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计