CVE-2019-1040 Drop The MIC漏洞

前言:关于CVE-2019-1040 Drop The MIC漏洞学习笔记

参考文章:https://dirkjanm.io/exploiting-CVE-2019-1040-relay-vulnerabilities-for-rce-and-domain-admin/
参考文章:https://blogs.technet.microsoft.com/exchange/2019/02/12/released-february-2019-quarterly-exchange-updates/
参考文章:https://msrc.microsoft.com/update-guide/vulnerability/CVE-2019-1040
参考文章:https://github.com/fox-it/cve-2019-1040-scanner
参考文章:https://en.hackndo.com/ntlm-relay/#ntlm-relay
参考文章:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/83f5e789-660d-4781-8491-5f8c6641f75e

题外话

说下之前在笔记中记录了两篇关于CVE-2019-1040知识点攻击链路的实验文章,大家可以参考下

关于CVE-2019-1040涉及到知识点在该作者文章也已经描述总结,也就是基于RBCD和Exchange的攻击

上面说的"Exchange的攻击",它的版本是在2019年2月12日之前部署的版本,因为后续对Exchange权限已经进行了限制操作,如下图所示

参考文章:https://dirkjanm.io/exploiting-CVE-2019-1040-relay-vulnerabilities-for-rce-and-domain-admin/

关于Exchange权限限制操作的详细情况(相关补丁是KB4490059),如下图所示

回顾Windows LM/NT认证流程

参考文章:https://www.cnblogs.com/zpchcbd/p/11738923.html

关于LDAP/LDAPS签名协商问题

对于域控制器,这边可以通过注册表来查询关于LDAP的签名等级,如下图所示,如下图所示,可以看到状态为"协商签名"

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NTDS\Parameters

对于域机器,这边可以通过注册表来查询LDAP的签名等级

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\ldap

这边有一张hackndo作者总结出来的LDAP的协商图,如下图所示

从上面的注册表知道默认情况下域机器和域控制器都具有签名状态都是"协商签名",从上面的图中可以总结出对于域机器和域控制器默认情况下会对所有LDAP数据包进行签名。

从上面的图中进行对比的话,如果这边想要进行中间人中继利用的话,那么客户端此时的签名状态是需要为Disabled

在中继攻击中,中继的客户端想要通过SMB进行NTLM身份验证,默认情况下它支持数据包NEGOTIATE_SIGN签名为1,如下图所示

其中绕过签名的一种方法是我们通过LDAPS中继其身份验证,而不更改任何内容,那么LDAPS服务器将看到此NEGOTIATE_SIGN标志为1的时候,并且将终止身份验证阶段,但是LDAPS并不是默认设置,默认情况下还是LDAP的情况,所以这边就简单的提一下,不继续深究

关于"为什么LDAPS对于NEGOTIATE_SIGN标志为1的时候,并且将终止身份验证阶段的"原因是LDAPS是基于TLS的LDAP,并且是处理数据包签名(和加密)的TLS层,所以对于LDAPS客户端没有理由表明它可以对其数据包进行签名,如下图所示

MIC消息完整性代码(NTLM身份级别签名)

MIC(消息完整性代码)是一种可选的缓解措施,可保证NTLM消息的完整性。

MIC可防止攻击者在中继NTLM消息时篡改消息(即跨协议取消签名中继)。通过此缓解措施,攻击者无法删除会话签名协商标志。与会话签名不同,MIC保护身份验证。

这边的话也就是如果我们强制把NEGOTIATE_SIGN标志置为0是否可以呢?实际上还是不行,因为这边还有一个MIC字段的校验,这个MIC字段校验了完整的NTLM交互认证的数据

MIC字段的构成MIC=HMAC_MD5(Session key, NEGOTIATE_MESSAGE + CHALLENGE_MESSAGE + AUTHENTICATE_MESSAGE)

大家可能会想到上面提到的"MIC(消息完整性代码)是一种可选的缓解措施",那么如果我把这个MIC字段删除的话,那么最终就能实现NEGOTIATE_SIGN为0并且MIC不校验NTLM数据包的情况了

这种情况也不行,实际上还有一层对MIC的校验,也就是NTLM响应包中的msAvFlags字段

msAvFlags

msAvFlags字段也存在于NTLM响应中,如果它是0x00000002,则它告诉服务器必须存在MIC。如果服务器没有看到MIC,它会终止当前的身份验证。

CVE-2019-1040漏洞

  • 取消设置NTLM_NEGOTIATE消息中的签名标志(NTLMSSP_NEGOTIATE_ALWAYS_SIGN,NTLMSSP_NEGOTIATE_SIGN)

  • 从NTLM_AUTHENTICATE消息中删除MIC

  • 从NTLM_AUTHENTICATE消息中删除版本字段(删除MIC字段而不删除版本字段将导致错误)。

  • 取消设置NTLM_AUTHENTICATE消息中的以下标志:NTLMSSP_NEGOTIATE_ALWAYS_SIGN,NTLMSSP_NEGOTIATE_SIGN,NEGOTIATE_KEY_EXCHANGE,NEGOTIATE_VERSION

CVE-2019-1040的出现带来了什么新的利用

为什么会出现跨协议中继的利用,首先的原因就是对于域控制器默认的话需要SMB签名,攻击者就不可能通过SMB中继此身份验证,即使配合CVE-2019-1040也不行,因为域控制器默认的话需要SMB签名

假设攻击者设法将自己置于客户端和域控制器之间的中间位置,并且他通过SMB接收身份验证请求。然而对于域控制器默认的话需要SMB签名,攻击者就不可能通过SMB中继此身份验证。

域控制器上面进行查询reg query HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NTDS\Parameters,结果如下图所示

而攻击者可以将SMB中继域机器到域控上LDAP/LDAPS协议,因为身份验证和会话应该是独立的。

在当在跨协议LDAP中继的时候,同样也存在一个协商的问题,但是这边的话配合CVE-2019-1040能够绕过协商签名的交互,所以这里CVE-2019-1040带出来了LDAP跨协议的利用

CVE-2019-1040和跨协议LDAP时的签名协商

下面的图中可以看到我标注的no-cve-2019-1040,意思是指如果中继跨协议的话是无法利用成功的

而其中的cve-2019-1040,可以看到当NEGOTIATE_SIGN为0,并且不校验NTLM级校验MIC的情况下,那么中继跨协议就可以利用成功

而这里的NEGOTIATE_SIGN为0,并且不校验NTLM级校验MIC的情况其实也就是cve-2019-1040的效果

一个有意思的问题

这里说下这个问题的结果其实没有意义,只是让自己多理解下NTLM协议以及中继的利用,然后进行记录下

ubuntu 192.168.75.198

win2016 域控制器 192.168.75.22

win2016 域机器 192.168.75.66

个人理解的CVE-2019-1040可以将MIC消息完整性代码以及NEGOTIATE_SIGN置0的来实现所谓的签名绕过的利用,那这句话是否正确呢?

如果上面的是正确的,那么如果我将域机器192.168.75.66登录域管的账号,然后在域机器192.168.75.66上面执行dir \\192.168.75.198\c$,此时我ubuntu将当前基于SMB的NTLM验证中继到域控制器192.168.75.22上,是成功的吗?

ubuntu开启ntlm中继攻击,执行sudo -E python3 ntlmrelayx.py -t smb://192.168.75.22 -smb2support --remove-mic,如下图所示

在域机器192.168.75.66上登录域管administrator账号,然后执行dir \\192.168.75.198\c$,如下图所示

ubuntu上中继的结果如下图所示,可以看到结果是没有执行成功

这里的原因还是SMB签名的问题,参考如下图可以知道,此时的情况就是标注红框中的情况

检测CVE-2019-1040

参考文章:https://github.com/fox-it/cve-2019-1040-scanner
参考文章:https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-nlmp/83f5e789-660d-4781-8491-5f8c6641f75e

python3 cve-2019-1040-scan.py hengge/alimaomao:admin@123@192.168.75.68

上面的图中可以看到192.168.75.22机器是不存在的,因为.22的机器是域控制器

这边主要看mod_computeResponseNTLMv2,作者重写了一份Type3发送请求的过程

查看正常的Type3和作者重写的Type3的区别,如下图所示

可以看到的是作者添加了av_pairs[NTLMSSP_AV_FLAGS] = b'\x02' + b'\x00' * 3

我这边先抓下默认impacket的smb通信的数据包,可以看到在协商Type1中客户端(impacket)就表示了Negotiate Sign为0,说明不支持sign签名情况

而这个时候如果你添加av_pairs[NTLMSSP_AV_FLAGS] = b'\x02' + b'\x00' * 3,那么当服务端接收到了该条目的时候就会校验MIC字段,而客户端没有生成MIC字段,那么如果报错的话则对方会校验,如果不报错的话那么对方不校验,不校验的话就是漏洞存在的情况

这边稍微再提及下,如果你用这个脚本去检测exchange的服务器你会发现如下所示,我这边的exchange服务器的地址是192.168.75.204

python3 cve-2019-1040-scan.py hengge/alimaomao:admin@123@192.168.75.204

执行完之后你会看到检测的结果是不存在该漏洞,原因是exchange服务器的本地组策略会跟域控制器的本地组策略对于网络通信的签名配置是一样的,如下图所示,可以看到同样当作为服务端进行通信的时候,签名也是强制要求的

防护手段

  • 开启所有重要服务器的强制 SMB 签名功能(在Windows域环境下,默认只有域控服务器开启了强制SMB签名)

  • 启用所有域控服务器的强制 LDAPS Channel Binding 功能(此功能默认不启用,启用后有可能造成兼容性问题。)

  • 启用所有域控服务器的强制 LDAP Signing 功能(此功能默认不启用,启用后有可能造成兼容性问题)

posted @ 2023-12-15 22:50  zpchcbd  阅读(60)  评论(0编辑  收藏  举报