信任安全 | 天啊!将NTLM哈希武器化为密码字典
文章正文
密码重用现象在Active Directory (AD) 环境中十分普遍。从攻击者的角度来看,这是实现横向移动或权限提升的一条可靠路径。尽管大多数IT团队都意识到了这种风险,但更长的密码和密码管理器的使用,让人们常常误以为重用长密码是安全的。一旦密码长度达到很高的字符数,对于许多哈希类型而言,恢复它们通常是不切实际的,而这种重用行为往往就因此被忽视了。
这就引入了“哈希剥离”技术。我们不再尝试从Kerberos票据或缓存凭据等较慢的算法中恢复明文密码,而是可以将NTLM(NT)哈希作为密码字典,在Hashcat的NT模式下使用。这让我们能够快速验证密码在NTLMv1和NTLMv2质询-响应、Kerberos 5 etype 23票据以及DCC/DCC2哈希之间的重用情况。如果找到匹配项,我们就可以更有效地利用时间,从NT哈希中恢复明文,或者直接使用哈希传递(Pass-the-Hash, PtH)。在本文中,我将描述哈希剥离技术及其与AD的相关性,概述涉及的关键Hashcat模式,通过两个示例演示该技术,并以限制哈希剥离机会的实用缓解措施作为结尾。
什么是哈希剥离?
假设一家公司运营着两个站点。站点A被入侵,暴露了未加盐的MD5哈希:
|
|
后来,站点B通过用bcrypt包装现有密码来升级密码存储。它同样被入侵,暴露了:
|
|
利用站点A泄露的MD5哈希和站点B泄露的、经过bcrypt包装的MD5哈希,你可以直接将站点A泄露中的MD5值提供给bcrypt函数:
|
|
如果bcrypt校验匹配,我们就确认了密码被重用,而无需恢复明文。这就是哈希剥离:外部层(bcrypt)被剥离,你可以以更高的速度针对内部哈希(MD5)运行密码恢复攻击。我推荐查阅Sam Croley的《这算什么剥离?分层哈希剥离》以获取更详细的解释。
这与AD有何关联?
AD中的密码以NTLM哈希的形式存储在域控制器上。NT哈希是通过对密码的UTF-16LE编码进行MD4运算得出的。
|
|
Kerberos支持多种加密类型。当允许使用RC4-HMAC(etype 23)时,可以请求使用目标账户NT哈希派生的密钥加密的TGS票据。使用任何域用户,你可以为具有SPN的账户请求TGS,捕获生成的TGS-REP,提取基于RC4的TGS-REP哈希,并将其离线进行密码恢复。
|
|
如果提供的NT哈希作为候选者验证了TGS-REP哈希,你就证明了使用了相同的密码。从那里,你可以剥离外部层,然后从NT哈希中恢复明文,或者跳过恢复步骤直接使用哈希传递。
这种剥离方法同样适用于任何以NT哈希为基础密钥的场景。这包括:
- NTLM质询-响应:NTLMv1和NTLMv2
- Kerberos 5, etype 23票据:AS-REQ预认证、TGS-REP和AS-REP
- 缓存凭据:DCC和DCC2
注意:在撰写本文时,Hashcat中尚未为Kerberos 5, etype 23 AS-REQ预认证提供NT候选模式。
剥离还是不剥离?
当AD环境中存在密码重用时,哈希剥离可以节省大量时间。你无需在慢速哈希格式上消耗计算资源,而是可以通过测试NT哈希作为候选者来快速确认多个目标之间的重用情况。这些NT候选者最好来自同一AD环境。最丰富的来源是域控制器的NTDS提取,这通常能产生数千个哈希。Windows终端上的SAM/SECURITY注册表配置单元提取也可用,但由于LAPS(本地管理员密码解决方案)和本地账户使用不频繁,其价值通常较低。该技术在多域或信任场景中尤其有价值:如果你控制了一个域并获得了其NT哈希,并且能够在另一个域中捕获基于NT的哈希,剥离技术可以让你快速验证重用情况,并优先处理高价值的横向移动目标。
当你拥有NT哈希和基于NT的目标时,都应该尝试剥离。即使是一个原本无法破解的60字符密码短语,如果你有相应的NT哈希,也可以验证其重用情况。然后,你可以从NT哈希离线恢复明文,或者直接使用NT哈希通过哈希传递进行身份验证。
攻击NT哈希要快得多。在Apple M3 Max上,Hashcat的NTLM(模式1000)运行速度约为每秒300亿次哈希运算(30,000 MH/s),而TGS-REP(模式13100)的运行速度约为每秒3亿次哈希运算(300 MH/s),速度优势大约为100倍。虽然这个差距没有计入测试重用所花费的时间,但针对基于NT的捕获运行Hashcat的NT哈希模式只会增加极少的额外运行时间。
图1 - Hashcat NTLM(1000)基准测试 图2 - Hashcat TGS-REP(13100)基准测试
但所有这些剥离的乐趣也有其限制。Kerberos 5 etype 17和18不是从NT哈希派生而来的,因此基于NT的剥离不适用于它们。如果AD域强制使用AES,并且你无法请求RC4/etype 23,则必须回退到正常的密码恢复,并使用Hashcat中的AES Kerberos模式,例如etype 17(AES128)的模式19600和etype 18(AES256)的模式19700。
归根结底,当NT哈希来自你正在测试的同一环境时,哈希剥离的效果最好。你也可以使用大型数据泄露列表中的哈希,有可能找到匹配项,但这种方法耗时且成功率较低。Hashcat的NT剥离模式并不比普通的密码模式快,而且因为你输入的是固定的32位十六进制NT哈希,应用密码字典规则会破坏这些哈希,使其不再代表原始密码。
Hashcat剥离模式
为便于快速参考,下表列出了Hashcat密码模式及其对应的基于NT的剥离模式。
| 哈希类型 | 模式(密码) | 模式(NT) |
|---|---|---|
| 域缓存凭据(DCC) | 1100 | 31500 |
| 域缓存凭据2(DCC2) | 2100 | 31600 |
| NetNTLMv1 / NetNTLMv1+ESS | 5500 | 27000 |
| NetNTLMv2 | 5600 | 27100 |
| Kerberos 5, etype 23, AS-REQ预认证 | 7500 | 无 |
| Kerberos 5, etype 23, TGS-REP | 13100 | 35300 |
| Kerberos 5, etype 23, AS-REP | 18200 | 35400 |
演示时间
在这些演示中,假设SMOKE.LOCAL域已被入侵,并通过使用Impacket的secretsdump.py执行DCSync攻击获取了NT哈希:
|
|
图3 - 对SMOKE.LOCAL执行DCSync攻击
当你执行DCSync攻击时,应该同时针对密码历史记录。使用secretsdump.py时,可以通过-history标志实现。微软建议在历史记录中保留最多24个先前密码以减少重用,但从攻击者的角度来看,这显著增加了获取的NT哈希数量。用户不总是拥有完整的历史记录,但即使每个账户只有几个历史密码,也能极大地扩展恢复的密码数量以及用于剥离的NT哈希密码字典。同样的逻辑也适用于使用Mimikatz或类似工具在Windows终端上转储SAM时:历史哈希为你提供了更多用于剥离的候选哈希,并揭示了可用于预测当前可能密码的密码更改模式。
图4 - 带有密码历史记录的扩展NT哈希密码字典
最后,请确保你使用的是最新版本的Hashcat,因为以下演示中使用的基于NT的剥离模式需要较新的版本。
演示 1:Kerberoast场景
在此演示中,使用一个低权限用户对CHOKE.LOCAL执行Kerberoast攻击。使用Impacket的GetUserSPNs.py为CHOKE.LOCAL\roastable账户请求服务票据,返回一个Kerberos 5 etype 23 TGS-REP哈希。该哈希被保存到roastable_TGS文件中,$krb5tgs$23$格式表明它是基于RC4的。
|
|
图5 - 从Kerberoast攻击中获取TGS哈希
接下来,使用Hashcat的NT候选模式35300,利用从CHOKE.LOCAL获取的TGS哈希和从SMOKE.LOCAL获得的NT哈希密码字典。Hashcat能够将TGS-REP与密码字典中的某个NT哈希匹配,表明CHOKE.LOCAL\roastable账户重用了密码。
|
|
图6 - 将TGS-REP剥离至NT哈希
然后,通过NetExec使用该NT哈希,以CHOKE.LOCAL\roastable的身份通过SMB认证到CHOKE.LOCAL域控制器,在实践中演示了跨域密码重用。
|
|
图7 - 使用NT哈希认证到CHOKE.LOCAL
演示 2:域缓存凭据场景
在此演示中,使用本地管理员账户localadmin,对CHOKE.LOCAL域中一台已加入域的 workstation 执行LSA机密提取。使用NetExec提取LSA机密,其中包括CHOKE.LOCAL\highpriv账户的DCC2哈希。然后将该DCC2哈希复制到名为DCC2_hash的文件中以供离线测试。
|
|
图8 - 从LSA机密中提取DCC2哈希
然后使用Hashcat的NT候选模式31600,将DCC2哈希作为目标,并使用从SMOKE.LOCAL获得的NT哈希密码字典。
|
|
图9 - 使用NT哈希认证到CHOKE.LOCAL
利用该NT哈希,NetExec以CHOKE.LOCAL\highpriv的身份通过SMB认证到CHOKE.LOCAL域控制器,再次在实践中演示了跨域密码重用。
|
|
图10 - 使用NT哈希认证到CHOKE.LOCAL
缓解措施
密码重用是使得哈希剥离成为可能的核心问题。用户账户和服务账户不应跨域、林或权限层级共享密码。服务账户应使用gMSA或其他托管凭据,而不是静态密码。在多个账户之间重用相同的秘密,实际上消除了这些账户旨在提供的权限分离。
Kerberos配置是一个主要的控制点。环境应优先选择AES etype 17和18,并尽可能逐步淘汰域账户和服务账户的RC4/etype 23。在收紧允许的类型之后,应轮换密码,以便派生新的AES密钥,并使任何现有的基于RC4的票据失效。
需要控制本地管理员重用和特权登录。终端上的本地管理员密码应使用LAPS、Windows LAPS或类似的控制措施进行管理,以便每个主机都有唯一的、可轮换的本地管理员凭据。域管理员和其他第0层账户应限制在普通工作站上进行交互式登录,这样它们的缓存凭据就无法轻易通过本地管理员访问被提取。
结论
如两个演示所示,哈希剥离使得检测和利用密码重用成为可能,而无需恢复底层密码。Kerberoast示例使用了NT哈希1269258dd36b6ed22bdd1f7774954fa6,它来自密码:
|
|
这种字符串在正常的渗透测试任务中实际上是无法破解的,然而剥离技术仍然可以让你证明重用并实现横向移动。DCC2示例使用了520adba9cd842298ea83c576a2a1de02,这是一个更现实的、可以通过标准密码字典和规则恢复的密码。我把这个留给读者作为练习。
虽然哈希剥离将NT哈希变成了用于其他NT派生格式的高价值密码字典,但它并不能完全替代密码恢复。然而,在攻击性任务中,它可以通过证明重用和实现访问权限(即使底层密码实际上无法恢复)来提供快速的胜利。
致谢
- Sam Croley - 原始的哈希剥离研究
- Hashcat团队 - 构建和维护Hashcat
- Justin Bollinger - 博客审阅
- Hans Lakhan - 术语和概念的合理性检查
其他参考资料
- https://github.com/Pennyw0rth/NetExec
- https://github.com/fortra/impacket
- https://github.com/gentilkiwi/mimikatz
- https://github.com/hashcat/Hashcat
- https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/security-policy-settings/enforce-password-history
- https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/security-policy-settings/network-security-configure-encryption-types-allowed-for-kerberos
- https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/hh831782(v=ws.11)
- https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-overview
- https://www.scottbrady.io/authentication/beware-of-password-shucking
- Sam Croley - What the Shuck? Layered Hash