Ntlm Rleay简介
Ntlm Rleay翻译过来就是Ntlm 中继的意思,也肯定是跟Ntlm协议是相关的,既然要中继,那么攻击者扮演的就是一个中间人的角色,类似于ARP欺骗,ARP欺骗就是在一个广播域中发送一些广播,然后大声问这个IP地址的MAC地址是多少啊???如果有不怀好意的人回答了,那么就造成了ARP欺骗,好似一个中间人攻击。
就比如说有一个客户端和一个服务端,客户端请求服务端的某个服务,需要身份验证,客户端提供身份验证,服务端响应,这原本是一次很正常的流程,但是如果加入了攻击者这个角色,那么就变成了攻击者发送同样的消息给服务端,服务端进行响应,然后交给攻击者,攻击者返还给客户端。
那么我们可以想象其实攻击者就是充当了一个代理转发点。
看一下如下图:
攻击者在客户端和服务端的中间,也就是说你客户端发送的无论是质询,响应,认证,我攻击者都是可以收到的,为什么会收到?,因为客户端以为攻击者是服务端,而正好相反,服务端以为攻击者是客户端,这就造成了,客户端将数据给攻击者,攻击者再将数据发送给服务端,同样服务端返回数据给攻击者,攻击者也返回数据给客户端,那么这中间如果攻击者对数据进行了修改,或者说发送给其他人了,并没有发送给原来的客户端,那么就可能造成了安全问题。
Ntlm Relay测试分析
这里的测试环境:
域:relaysec.com
user-win7 10.211.1.2
dc 10.211.1.210
kali 10.211.1.45
这里我们使用ntlmrelay.py
ntlmrelay.py可以将获取到Ntlm中继到内网的其他机器。
这里表示的意思就是,如果我获取到了其他机器的SMB凭据,我中继给1.2这台机器。
紧接着我们到DC上面去请求一下攻击者这台机器。
去dir \10.211.1.45\addwadwa 只需要访问到攻击者的SMB服务即可。
我们这里wireshark抓包,我们需要着重注意红框中的6个包。
他们分别代表着 协商,质询,认证。
我们先来简单看一下这个包,会发现其实攻击者一直在做一个转发的事情,攻击者就是一个代理转发点,一直转发着客户端和服务端的数据。
我们先来看第二组包,也就是DC给攻击者发送质询包的时候。
我们直接来看质询值,会发现客户端发送给攻击者的质询值和攻击者发送给DC的质询值是没有改变的。这两个包其实是一样的。
也就是说当攻击者收到这个请求的时候,他会原封不动的将包发送给210。
我们可以看到攻击者只是在转发东西,它只是将信息从客户端传递到服务端,只是最后服务端以为攻击者身份验证成功,所以攻击者可以代表DC去WIN7这台机器上操作。
这里中间还有SSPI和NTLM SSP这里当作了解即可,可以看之前的NTLM协议那篇文章。
会话签名
签名其实就是一个校验数据在发送期间有没有被更改的方法,比如说张三给李四发送了一个hello world的文档,并且对这个文档进行了数字签名,那么任何收到该文档并且和他签名(张三)的人都可以验证编辑它的人是张三,并且可以确定他写了这句话。因为签名保证文档没有被修改,只要协议支持,签名原则可以应用于任何协议,例如SMB协议,Ldap协议,HTTP等等,但是在实际情况中,HTTP前面很少实现。
签名的意义就是当客户端想要访问服务的时候,由于攻击者可以处在中间人的位置并且中继身份信息,因此他可以在于服务器交互的时候冒充客户端。这就是签名发挥作用的时候。
在Ntlm中继中,攻击者想要伪造客户端,但是他不知道的客户端的密钥,因此他就无法替客户端做任何事情。由于攻击者无法对任何数据包进行签名,因此接收到数据包的服务端查看有没有签名或者说这个签名对不对,如果不对或者没有签名的话,服务端直接拒绝攻击者的请求。
所以说数据包必须在认证后进行签名,那么攻击者就攻击不了了,因为他不知道客户端的密钥。
认证之后代表的是这个包: 协商->质询->认证
但是客户端和服务端如何才能达成一致的呢,就比如说我客户端想要签名,你服务端不知道我客户端想要签名,所以服务端如果不签名的话,又是什么情况呢?
所以来到了NTLM的协商阶段,也就是协商包呗。
NTLM 协商
这个协商包,我们之前已经再NTLM协议中了解过了这里直接来看他的标志位。
这里的有很多的协商标记,这里我在Ntlm协议哪里已经详细解释过了,我们这里主要看NEGOTIATE SIGN
这个协商标记设置的是1,他表示客户端支持签名,但是这并不代表服务端一定会签署客户端的数据包,只是客户端有这个能力。
同样当服务端回复的时候,如果支持签名的话,这个标记位也是1。
所以说,这种协商只是客户端向服务端表示我支持签名,同样服务端向客户端表示我支持签名,但是这并不意味着数据包就会被签名,就比如说HTTP协议,即使客户端和服务端都支持签名,其实实际上也会很少签名。
微软提供了标记位,用于确定SMB数据包是否基于客户端和服务端的设置来进行签名,而对于SMBV2的版本是必须处理签名的。
我们可以在HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanmanServer\Parameters注册表中更改EnableSecuritySignature键和RequireSecuritySignature键,这两个的值需要改成1。
注意:这里你不能只更改一台机器为SMBV2,否则还是不签名。
win7:
DC:
紧接着我们使用ntlmrelay.py工具进行攻击。
可以发现已经明显不行了。
我们来抓包看下:
首先这里我们不用kali来去做这个中继,我们直接访问1.2
然后进行抓包。
主要查看这两个包。
可以看到10.211.1.210去访问10.211.1.2的时候,签名状态。
这两个值其实就是我们上面在注册表中设置的值,我这里给10.211.1.210设置为了EnableSecuritySignature为1,RequireSecuritySignature为0。EnableSecuritySignature设置为1表示10.211.1.210支持签名,RequireSecuritySignature设置为0表示我不用签名。说的简单点就是虽然我支持签名,但是协商不签名。但是如果服务端需要签名的话,服务端可以处理我的签名。
我们再来看服务端也就是10.211.1.2。
这里它表示我不仅支持签名,我还需要签名。
那么在协商阶段的时候,客户端和服务端将NEGOTIATE_SIGN标志设置为1,因为他们都支持签名。完成身份验证之后,会话继续。
那么我们来测试一下,如果客户端没有设置签名,但是服务端设置了签名并且要求签名,能不能中继成功?(如下测试是对于SMBV1的)
显然是不行的。
那么如果服务单没有设置签名,客户端设置了签名,能不能中继成功?
我们发现是可以的。
wireshark如下抓包:
那么如果服务端支持签名,但是不需要签名,我们发现还是可以中继成功的。
那么也就是说服务端需要既支持签名又需要签名,客户端无论需不需要,都要签名。
如上的测试只需要改注册表的值即可,就是RequireSecuritySignature和EnableSecuritySignature这两个值改为0或1。
Ldap签名
Ldap签名有3个级别。
- 禁用: 这意味着不支持数据包签名。
- Negotiated Signing:此选项表示协商签名,如果与他通信的机器也协商签名,那么数据包就会被签名。
- 必须签名:这代表不仅支持签名,而且必须对数据包进行签名才能使会话继续。
在域控中Ldap签名是在HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NTDS\Parameters/注册表中的ldapserverintegrity选项,他的值可以为0,1,2分别代表着Ldap签名的级别。默认他的值为1。
那么对于客户端来说,Ldap签名设置是在HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\ldap注册表中。他的默认值也是1。
所以说服务端协商签名,客户端也协商签名,所以,所有的Ldap数据包都会被签名。(这里说的是Ldap的级别1)
那么如果一方需要签名,而另一方不支持签名,那么需要签名的一方会忽略未签名的数据包。(这里说的是Ldap级别2)
那么如果我们需要使用Ldap将身份验证中继到服务器,那么必须满足两个要求。
- 服务端不能设置为需要签名,也就是Ldap的级别为2,默认情况下所有的机器都是协商签名,而不是必须签名。
- 客户端不能设置NEGOTIATE_SIGN(SMB签名)为1,如果设置了那么客户端就希望签名,因为攻击者不知道客户端的密钥,所以就无法签署数据包。
关于第二点,那么客户端如果不设置此标记的话,那么是不是就可以中继了呢?Windows SMB客户端设置了它,默认情况下,我们无法将SMB身份验证中继到LDAP。
MIC签名
这里目前有一个环境,就是说我这台1.2机器上也就是服务端不仅支持签名而且需要签名,那么攻击者就无法通过SMB进行中继。
如下图:
我们使用ntlmrelay.py进行中继。可以看到是无法中继的。
所以我们在想,既然不能中继到SMB协议上,那么能不能中继到其他协议?比如Ldaps协议。
Ldaps对应的端口是636。
我们都知道NEGOTIATE_SIGN标记是用于客户端和服务端是否支持签名的,但是在某些情况下,LDAP/LDAPS会考虑这个标记。
对于LDAPS来说,服务端也会考虑这个标志,如果服务端看到客户端的NEGOTIATE_SIGN标记设置为1,那么服务端直接拒绝身份验证,这是因为LDAPS也是基于TLS的LDAP,他是会处理数据包签名的TLS层。
那么现在来说我们中继的客户端需要通过SMB进行身份验证,但是它支持数据包签名,它将NEGOTIATE_SIGN标志设置为了1,但是如果我们通过LDAPS来中继身份验证,但是LDAPS服务端也会看到这个标记,并且终止身份验证。
也就是说无论是SMB还是LDAP/LDAPS,看到这个NEGOTIATE_SIGN标记位设置为了1,那么就会终止会话,因为攻击者无法对数据包签名,攻击者不知道客户端的密钥。
那么我们能不能将这个标记给它干掉呢?就比如说给他删掉,这鸟标记太烦人了。
但是这个标记我们干不掉,因为在它的上面还有一个NTLM级别的签名,那么就是MIC签名。
MIC签名是如下计算的。HMAC_MD5(Session key, NEGOTIATE_MESSAGE + CHALLENGE_MESSAGE + AUTHENTICATE_MESSAGE)
最重要的是会话密钥是用客户端的密钥进行加密的,所以攻击者无法计算MIC值。
所以说啊,如果把将NTLM消息这部分改了,那么MIC就不会生效了,所以我们无法更改NEGOTIATE_SIGN标记。
那么我们能不能将MIC给它干掉呢?这是可以的,因为MIC是可选的。
那么它通过什么来可选的呢?
它是通过msAvFlags值来进行可选的,如果他的值为0x00000002那么它就会告诉服务器必须存在MIC,如果不存在的话,就会直接终止身份验证。
那么如果我们将msAvFlags的值设置为0,然后移除MIC,是不是可以呢?
这样是不行的,因为当客户端请求服务端质询的时候,服务端返回NTLMV2 Hash,这个Hash它不仅仅考虑了质询,而且还考虑了所有标志的HASH,所以说MIC存在的标志也是响应的一部分。
也就是说更改或者删除MIC标记会使NTLMV2Hash无效。因为数据被修改之后它是这样子的。
MIC保护了协商,质询,认证这三条消息的完整性,而msAvFlags保护的是MIC的存在,NTLMv2 哈希保护标志的存在,因为攻击者不知道客户端的密钥,所以不能计算这个Hash值。
所以这种情况下我们是不能攻击的。
但是老外发现了一个相关的漏洞,CVE-2019-1040,它可以绕过NTLM MIC(消息完整性检查)保护。
已经集成到了ntlmrelayx.py --remove-mic
我们来使用一下:
可以看到这里成功将user4用户添加到企业管理组里面了,这里是通过SMB协议进行触发的,中继到了Ldap协议。这里中继的是ldap,ldaps也是可以的,这里的ip是210,因为只有域控有Ldap服务。
如下图可以看到user4已经是企业管理组的成员了。
CVE-2019-1040的漏洞范围是:
Windows 7 sp1 至Windows 10 1903
Windows Server 2008 至Windows Server 2019
那么你如果使用Ldaps去中继的时候会出现这样的问题。
这是因为你没有安装证书服务导致的,所以在AD控制面板哪里添加功能,选择证书服务。
如下图: 可以百度搜索安装ADCS证书服务。 这里可以参考:https://lework.github.io/2019/07/24/ad-install/#%E5%90%AF%E7%94%A8ldaps
之后我们使用LDP.exe连接Ldaps服务。
记得勾选上SSL即可。
紧接着我们再来Ldaps中继,可以发现成功了。
通道绑定
那么通道绑定是干什么的呢?就如我们上面看到的,我们可以通过跨协议中继,通道绑定就是为了解决这个问题。
其实就是将身份验证和正在使用的协议绑定在一起,攻击者就无法修改,如果客户端希望对服务器进行身份验证以及使用特定的服务,例如cifs等等,则将该标识性的信息添加到NTLM响应中,由于服务名称在NTLM响应中,所以因此它受到NtProofStr响应的保护,该响应是此信息以及其实和MIC计算的那个msAvFlags值是差不多的,都是使用客户端的密钥进行计算的。
就比如说客户端去请求服务端,客户端已经在他的NTLM响应中指明了他要访问的服务,并且由于攻击者无法修改它,当攻击者将请求中继给服务端的时候,将攻击者请求的SMB服务,和 NTLM响应中的HTTP服务进行对比,发现是不同的服务,所以直接拒绝连接。
如下图,客户端在NTLM响应中加了要访问的服务,攻击者如果中继给服务端是其他服务的话,那么服务端就会直接拒绝连接。
具体来说所谓服务其实就是SPN,之前的文档里面讲过。
可以看到它使用的是CIFS服务,也就是SMB协议,,不仅有服务名称 (CIFS),还有目标名称或 IP 地址。这意味着如果攻击者将此消息中继到服务器,服务器也会检查目标部分,并会拒绝连接,因为在 SPN 中找到的 IP 地址与他的 IP 地址不匹配。因此,如果所有客户端和所有服务器都支持这种保护,并且每台服务器都需要这种保护,那么它可以减少所有中继尝试。
那么怎么设置呢???
默认win2012是没有这个东西,网上资料显示是win10才新加的策略。
参考:https://learn.microsoft.com/zh-cn/windows/security/threat-protection/security-policy-settings/domain-controller-ldap-server-channel-binding-token-requirements
那些协议可以中继
NEGOTIATE_SIGN如果不需要签名,则任何未设置标记的客户端都可以中继到Ldap。
NTLMV1的危害
在NTLMV2中,NTLMV2哈希考虑了msAvFlags标记位,MIC字段,还有NetBios名称的字段等等,但是NTLMV2的哈希是没有任何附加信息的,例如没有MIC,目标名称,SPN等等。因此如果服务端允许NTLMV1身份验证的话,攻击者可以直接移除MIC字段,从而将身份验证中继到Ldap或Ldaps。
但更重要的是,他可以发出 NetLogon 请求以检索会话密钥。确实,域控制器没有办法检查他是否有权这样做。而且由于它不会阻止不是完全最新的生产网络,它会出于“复古兼容性原因”将其提供给攻击者。
这一点可以在ZeroLogon这个漏洞中进行体现。
总结
SMB V1中继到SMBV1 服务端如果没有设置签名,也就是RequireSecuritySignature和EnableSecuritySignature这两个值。那么就可以中继成功,无论客户端是否支持签名还是需要签名,是可以中继成功的。
SMBV2默认需要签名。
跨协议中继,SMBV2中继到Ldap服务,这是利用了CVE-2019-1040这个漏洞,这个漏洞可以绕过MIC签名。
SMBV2中继到Ldaps服务,需要安装ADCS证书服务。
通道绑定可以解决跨协议中继的问题,将服务的标识放在了NTLM响应中,从而和服务端的服务进行对比。