
2020年8月,Microsoft修补了CVE-2020-1472又名Zerologon。我认为,这是过去几年中最关键的Active Directory漏洞之一,因为它允许在没有凭据的情况下立即升级到Domain Admin。利用此漏洞的最直接方法是更改域控制器计算机帐户的密码。这是一个冒险的举动,并有可能破坏环境中的事物。在此博客中,我们探索了一种利用此漏洞的新方法,尽管它具有一些先决条件,但对于评估网络安全性的安全专业人员而言,它更安全。我们还将进一步研究Active Directory中的身份验证协议,以及如何将它们与Zerologon漏洞联系在一起。尽管这是利用漏洞的另一种方法,
零登录
让我们从漏洞开始。如果您尚未阅读详细信息,可以在Secura博客上阅读有关详细信息发现漏洞的研究人员Tom Tervoort在其中描述了技术细节。该漏洞存在一个加密漏洞,其中对于每256个随机生成的密钥中的1个,对由所有空字节组成的纯文本进行加密将导致所有空字节的密文。这种易受攻击的加密协议实现用作Netlogon协议中的身份验证机制。netlogon协议在Active Directory中通常由工作站和服务器使用,以通过安全通道与域控制器进行通信。之所以可行,是因为加入Active Directory的每个工作站或服务器都有一个知道密码的计算机帐户。Active Directory拥有从此相同密码派生的几个密钥,
最初的Zerologon攻击通过将域中域控制器的Active Directory帐户的密码重置为空字符串而起作用。这使攻击者可以将该域控制器认证为另一个域控制器,甚至是同一域控制器。能够作为域控制器进行身份验证具有很高的特权,因为域控制器可以使用DRSUAPI协议来同步Active Directory数据,包括NT哈希和Kerberos密钥。这些密钥又可用于模拟域中的任何用户,或创建伪造的Kerberos票证。利用这一点并非没有风险。在Active Directory中重置域控制器计算机帐户密码后,DC处于不一致状态。加密的计算机帐户密码,该密码存储在注册表和以下文件的内存中
lsass.exe
,不变。现在,已更改Active Directory中同一帐户的密码,这将影响从该域控制器进行的身份验证以及从该域控制器进行的身份验证。如果重新启动域控制器,则各种服务将不再启动,因为它们希望从Active Directory中读取信息。上周,我写了一个主题,内容涉及重置此计算机帐户后一切为何中断,您可以在此处阅读。如果执行漏洞利用的速度足够快,则可以从注册表中恢复原始密码,并使用我添加到包含示例漏洞利用的GitHub存储库中的还原脚本来还原该密码。同时,这仍然存在发生故障的风险,这就是为什么我不建议在生产环境中真正使用它的原因。
寻找替代方法来利用Zerologon
由于原始攻击有相当大的风险,因此我想找出一种无需重置计算机帐户即可利用Zerologon的方法。为此,我们必须同时考虑身份验证协议和Netlogon中的一些先前的缺陷。在Active Directory中,有两种主要的身份验证协议:NTLM和Kerberos。Kerberos是部分分散的,并且基于加密和共享机密工作。但是,NTLM是完全集中的,如果使用域帐户,则需要与域控制器进行通信才能正常工作。这是因为NTLM使用质询-响应认证机制,其中对服务器发送的质询执行加密操作,以证明用户拥有其密码(或确切地说是其密码的哈希版本)。对于Active Directory帐户,服务器实际上并不知道尝试进行身份验证的用户的密码,因此它将密码转发给域控制器,该域控制器告诉服务器响应对于给定的挑战是否正确。这种转发实际上是通过Netlogon协议完成的,该协议中存在Zerologon漏洞。
NTLM协议的弱点之一是,如果攻击者可以说服用户使用NTLM对他们进行身份验证,则他们可以将身份验证消息转发到其他服务器,并在该服务器上模拟用户。这被称为NTLM中继,已经存在了很长时间。几个保安措施已经介绍,多年来,以减少NTLM中继的有效性,但时不时有些漏洞往往会弹出这再次允许攻击者滥用它,并接管系统。
NTLM的一种攻击途径具有很大的潜力,被认为是一种设计,是Will和Lee于2018年发现的“打印机错误”功能。这是一个有趣的功能,因为它允许攻击者通过NTLM触发任何启用了spoolservice的计算机的身份验证。通过使计算机帐户向攻击者的IP地址而不是主机名进行身份验证,也可以强制使用NTLM进行此身份验证,这使它使用NTLM而不是Kerberos。但是,默认情况下无法将身份验证中继到有用的目的地,因为身份验证是通过SMB协议进行的,每当我们使用SMB协议与域控制器进行通信时,都需要使用加密签名。我已经讨论了细节 在以前的博客中对此进行了广泛讨论。
要了解此博客中描述的新攻击途径,我们需要了解使用NTLM协议执行身份验证时数据的签名和加密如何工作。用于签名和加密消息的加密密钥称为会话密钥,它基于用户的NT哈希和协议中协商的某些属性。这意味着,为了计算会话密钥,服务器需要拥有用户的NT哈希。除非服务器是域控制器,否则它不会拥有该NT哈希。因此,它使用Netlogon RPC协议将身份验证消息发送到域控制器,该协议将该会话密钥返回给服务器。
现在,有趣的是,Zerologon为我们提供了netlogon协议的身份验证绕过。将其与中继结合使用时,我立即想到了几年前Alberto Solino发现的CVE-2015-0005。此CVE允许任何计算机帐户请求会话密钥,从而可以将身份验证中继到需要签名和/或加密的端点。如果我们可以使用Zerologon达到相同的目的,那么任何接受NTLM身份验证并允许特权访问的协议都将成为潜在的目标。
中继到DRSUAPI以进行即时DCSync
目标是什么有趣的协议?使用打印机错误,我们可以获取任何计算机帐户,以对由攻击者控制的SMB服务器进行身份验证。机器帐户通常不具有高特权,尽管可能会授予它们管理员权限。特权最高的帐户是域控制器,可以使用DRSUAPI同步Active Directory数据库。最初的Zerologon POC也滥用了此权限,在该POC中重置了计算机帐户密码并获得了DCSync的权限。从技术角度来看,更有趣的是,如果我们可以避免更改密码,而使用中继连接直接向DRSUAPI协议的RPC端点进行身份验证。虽然此协议需要签名和加密,但也许我们可以使用Zerologon获取会话密钥,
分为Netlogon和NTLM
用来漏洞利用CVE-2015-0005漏洞的代码仍然存在,所以我决定从此开始,看看是否可以让SMB中继到需要签名的域控制器。我们没有使用计算机帐户进行身份验证,而是使用Zerologon POC中的代码完全绕过身份验证,并假装与我们要中继的计算机相同。这需要对代码进行一些编辑,以确保其在TCP上使用RPC,而不是在命名管道上使用RPC,但是将其与CVE-2020-1472 POC中的代码结合起来,这相对简单。通过从Windows框设置的手动连接进行尝试,我们看到它成功中继到需要签名的DC。
...
这里正在运行的netlogon操作就是该
NetrLogonSamLogonWithFlags
功能。当与本杰明·德尔皮(Benjamin Delpy)讨论这种攻击时,我们最初很惊讶地发现这种方法有效。根据文档,调用此函数时,应使用netlogon会话密钥对NTLM会话密钥进行加密,因为我们绕过了身份验证,因此我们不知道该密钥。进一步的挖掘将我们带到此页面进行解释。由于
ValidationLevel
我们指定的是
NetlogonValidationSamInfo4
,该值这个参数是6,而根据该表的手段,没有什么是加密!我不确切知道其背后的逻辑是什么,但是因此,可以调用
可以用作Zerologon的任何帐户,并从中获取NTLM身份验证的纯文本会话密钥。
中继到DRSUAPI
从理论上讲,我们应该能够使用与SMB中继中相同的逻辑来中继至DRSUAPI,当然中继RPC是一个完全不同的协议。幸运的是,最近由Arseniy Sharoglazov将RPC中继客户端添加到ntlmrelayx中。我们可以将该代码作为开发DCSync客户端的基础。由于使用DRSUAPI协议需要签名和加密,因此我们必须确保在初始化连接时进行协商
RPC_C_AUTHN_LEVEL_PKT_PRIVACY
。中继所有3条NTLM消息之后,我们应该能够通过Netlogon获得签名密钥,并且我们应该能够通过连接发送任何操作。
当然,事情从未像看起来那样简单。我写完允许这样做的代码后,主要是通过复制来自impackets secretsdump中与DRSUAPI进行交互的现有代码,我期望一切正常,但遭到错误消息的欢迎:
我花了一些时间比较secretsdump发送的数据包和中继时发送的数据包,发现了一个重要的区别。在NTLM协商消息中,因为DRSUAPI要求同时使用两个密钥,所以secretsdump会将两个标记(用于密封)与签名一起放置。SMB协议中的NTLM在默认情况下仅启用签名标志,并将密封标志保留为空。当我们将其中继到DRSUAPI时,服务器认为我们不想加密消息,并抛出错误,因为此RPC接口不允许这样做。
...
我在SMB设置上进行了一些尝试,以查看是否可以说服客户端启用密封标志。但是,无论我进行了什么配置,即使我强制执行SMB加密并且Windows将在SMB协议级别对所有消息进行加密,在NTLM中仍然不会设置密封标志。这是一种奇怪的情况,因为在这种情况下,我们实际上要使用比协商的客户端更多的安全性,而服务器无法接受该安全性。注意:在此博客中,我们要认证的服务器也是域控制器,但是由于通常应用该原理,因此我将使用“服务器”一词来描述我们最终要认证的目标,以避免术语混淆。
我想知道是否有可能更改NTLM消息以实际更改我们自己的签名标志。这样做会破坏NTLM 3类消息的一部分的消息完整性代码(MIC),该代码基于对所有3条消息的加密计算。从以前的研究中,我知道MIC不是由域控制器验证的,而是由我们要验证的本地服务器验证的。查看文档时这也很有意义发送给DC进行验证的信息,其中仅包含服务器质询和来自客户端的响应。MIC甚至没有发送到DC进行验证,这意味着它仅由服务器本地验证。这意味着对于使用DC验证消息,MIC并不重要,因此我们可以很高兴地更改消息中的协商标志。对于服务器身份验证,我们向然而,MIC事做,它会进行验证。但是,如果服务器不知道用户密码,该如何验证MIC?如果我们查看用于计算MIC的NTLM文档,就会发现它是使用会话密钥的3条NTLM消息的HMAC。作为秘密。您知道,我们通过向DC发送身份验证消息而获得的会话密钥…
结合这些知识,我们可以确保通过执行以下步骤在NTLM交换中协商签名和密封:
在初始继电器阶段,请确保已设置签名和密封标志。 收到NTLM类型3消息(“身份验证”消息)后,我们通过Netlogon将其转发到DC,并滥用Zerologon进行身份验证。 DC为我们提供了会话密钥,通过该密钥我们可以重新计算MIC。 现在,我们将带有重新计算的MIC的修改后的类型3消息转发到目标计算机。 我们通过签名和盖章谈判进行了认证。解决登录限制
在使用Negotiate标志执行魔术之后,我们可以将消息发送到RPC端点,并使用从DC获得的会话密钥对它们进行签名和加密。现在我们可以进行DCSync了!如果我们中继的帐户是域管理员,则可以正常使用:
...
当我使用打印机错误技巧进行身份验证时,它将拒绝该
操作,并指出不允许对计算机帐户进行身份验证。我想知道这是否是某种缓解措施,因为我的目标是DC并尝试使用计算机帐户登录。当我尝试使用非DC进行相同操作时,它确实给出了相同的错误消息,表明还有其他情况。这让我感到困惑,因为当我使用计算机帐户通过网络向Windows主机进行身份验证时,它不会引发此错误。Windows也使用
通过Netlogon进行操作,并且不会中断,因此必须有所不同。由于Windows正在加密所有操作,因此我们也看不到它通过线路发送的内容。因此,我们求助于一些逆向工程和调试,以查看是否可以找到遍历整个行的值。好消息是,有人在调试LSASS的过程中设法追踪了x64dbg为何冻结的问题,并且现在此问题已得到解决,因此我不必费心尝试了解Windbg。在中
netlogon.dll
,有一个函数
,需要很多参数。我们在函数上放置一个断点,并尝试查看是否找到对
NETWORK_TRANSITIVE_INFO
Wireshark中也看到的的引用:
...
在跟踪了几个指针之后,我发现了第6个参数,该参数指向一个指向看起来非常相似的结构的指针,包括
0x16
域长度的值。此后的指针
确实确实指向字符串“ TESTSEGMENT”,并且标志和logonID均为0。当查看由真实Windows主机转发的身份验证的相同结构时,我们看到Windows并不将0用于标志,但使用
0xE02A0000
。它还不会保留登录ID为:
...
如果我们在中继脚本中使用相同的标志,则允许计算机帐户进行身份验证,并且我们可以成功进行DCSync。实际上,我在此上花费了太多时间,因为我
flags
在中继脚本中使用了该变量,该变量显然已经用于其他重要事项,从而导致数据包加密中断。这使我在工作版本中来回移动了很多。
使用单个插座进行DCSync
同步DC上所有用户的代码是secretsdump的一部分。由于我不喜欢重复的代码,因此尝试导入
NTDSHashes
该类并将经过身份验证的RPC连接传递给该类。此类也确实依赖SMB连接进行一些查找并枚举域中的所有用户。在将另一个会话中继到SMB并将其组合在一起的同时,这将大大增加代码的复杂性。因此,我写了一些代码来绕过SMB连接的要求,并使用单个TCP连接进行转储。因为这样,我们无法一一列举所有用户,默认情况下该工具只转储krbtgt,DC$和Administrator
账户。使用这些帐户,您应该有足够的信誉,可以使用secretsdump执行完整的DCSync。
另外,也可以提供低特权凭证(无论如何利用打印机漏洞都是必需的),这些凭证将用于通过SMB连接并收集所需的信息。
全面进攻
所有这些加在一起,我们有了一种全新的攻击方式,它不依赖于重置要利用的计算机帐户密码。它确实有一些先决条件,即原始攻击不存在,尽管默认情况下存在这些先决条件,并且可能会在大多数广告中起作用:
需要一个帐户来触发打印机错误(如果您有权访问“加入域”框,则也可以在使用SSO的.NET中使用POC) 后台打印程序服务应在DC上运行 DC应该容易受到Zerologon的攻击 DC应该能够连接到攻击者工作站,并且不会被防火墙阻止 您应该能够运行Python并绑定到端口445以进行传入的SMB连接(在Windows上这很棘手) 域中至少应有2个DC,因为无法中继回同一DC总体而言,攻击看起来像这样:
...要在满足先决条件的情况下加以利用,则可以在DCSYNC中继模式和target下设置ntlmrelayx DC1,同时在以下位置触发打印机错误DC2:
...并且您应该看到连接和凭据滚动:
...当使用低特权帐户进行攻击以进行SMB身份验证时,所有哈希都将被:
...捍卫者注意事项
除了密码重置和可能来自非DC IP的DCSync,原始漏洞利用在事件日志中留下的痕迹很少。被滥用来向攻击者计算机触发身份验证的后台打印服务可能会留下跟踪,此仓库中提供了示例事件日志。网络IOC与原始的Zerologon相似,因为此攻击也使用相同的蛮力强制技术。如果您没有实验室,我已经提供了2个利用漏洞的PCAP,一个没有附加的枚举凭据,一个带有凭据。当然,最好的补救措施是尽快修补DC,因为不良行为者可能不会在意原始漏洞利用所涉及的风险。
代码和确认
此代码可在我的GitHub上找到,并且也已合并回impacket中。您可以从GitHub下载impacket,它应该已经具有最新文件。或者,您可以从我的存储库中获取这些文件,并将它们保存在
/impacket/impacket/examples/ntlmrelayx/
目录中,在2个文件的
clients/
和
attacks/
目录中。如果您要查找文件,它是我的krbrelayx存储库的一部分。
printerbug.py
该博客是许多其他人对NTLM进行了多年研究并将他们的代码贡献出来的成果。感谢:
Tom Tervoort找到了Zerologon错误 Alberto Solino完成有关流失的所有工作以及最初的Netlogon签名关键思想 Yaron Zinar和Marina Simakov在Drop-the-MIC和许多其他NTLM攻击方面的工作 Lee Christensen和Will Schroeder的打印机错误/功能 Arseniy Sharoglazov用于ntlmrelayx中的RPC中继客户端最后一点,中继到DCSync并不是这里唯一可能的攻击。由于我们可以随意编辑NTLM标志,因此我们还可以将DC帐户中继到LDAP,并滥用基于资源的约束委派,以允许我们以任何用户身份进行身份验证。如果需要LDAP签名,尽管ntlmrelayx目前不使用具有签名支持的ldap库,但我们也可以使用会话密钥进行签名。