ntlm relay攻击实验及攻击流程深度解析
这篇文章主要介绍ntlm relay攻击流程,以及作者在思考ntlm relay攻击时抛出的一些问题,和对这些问题的解决,先看一下ntlm relay攻击的过程
- 客户: 192.168.72.159
- 服务器: 192.168.72.174
- 中间人(攻击者): 192.168.72.162
首先说明以下,ntlm 作为底层协议,需要有其他高级协议的支持,比如说 smb、http,ntlm 嵌入这些协议里提供身份验证。
ntlm通信各个如下:
- ntlm身份验证阶段
- 第三方协议通信会话阶段
ntlm 身份验证阶段流程
客户向服务器发送 smb 请求,正常 ntlm 验证流程:
-
客户向服务器发送 ntlm 协商消息。
-
服务器向客户发送挑战消息,这里A主要作用如下:
- 返回第一步协商后的结果。
- 返回一个挑战值(随机生成的)。
-
客户对这个挑战值进行一系列运算,将运算结果作为认证消息发送给服务器。
-
服务器也经历同样的一系列运行,将是否认证成功作为结果发送给客户。
客户向服务器发送 smb 请求,中间人攻击后的 ntlm 验证流程:
-
客户向中间人发送 ntlm 协商消息,中间人转发给服务器。
-
服务器返回挑战消息给中间人,中间人转发给客户。
-
客户发送认证消息给中间人,中间人将认证消息转发给服务器。
-
服务器返回验证成功的消息给中间人,中间人获得一个会话。
-
此后中间人拒绝客户的所有连接,自己作为客户端与服务器交互。
实验1:常规 relay 攻击过程
第一步:
攻击者攻击:python3 ntlmrelayx.py -t smb://192.168.72.174 -c ipconfig -smb2support
受害用户受害:dir \\192.168.72.162\c$
第二步:分析数据包(我已经抓下来了)
查看所有关于客户(客户端)的信息,发现身份验证后的会话阶段,其向C发送的请求报文被C(攻击者)拒绝。
smb2 && (ip.src==192.168.72.159 || ip.dst==192.168.72.159)

查看所有关于攻击者的报文,发现身份验证后对目标攻击的过程。
smb2 && (ip.src==192.168.72.162 || ip.dst==192.168.72.162) && (ip.src != 192.168.72.159) && (ip.dst != 192.168.72.159)

同时攻击成功:

中继攻击的核心
核心在于验证阶段,服务器会验证客户发过来的哈希摘要,而这个摘要若被攻击者监听,且原封不动地中继过去,即可造成 ntlm relay 攻击。
mic 签名不是防止 relay
服务器通过验证 mic 来验证协商消息、挑战消息、验证消息是否被篡改,mic 实现原理如下:
HMAC_MD5(Session key, NEGOTIATE_MESSAGE + CHALLENGE_MESSAGE + AUTHENTICATE_MESSAGE)
攻击者的中继攻击是原封不动地发送客户端的协商消息、挑战消息、验证消息,包括 mic 签名,所以攻击者发送的数据都是服务器承认的合法数据。
由于受 mic 签名的影响,攻击者不能修改协商消息、挑战消息、验证消息,但可以在不影响中继攻击的前提下修改其他不受 mic 签名保护的内容,例如:
用户发给攻击者的协商数据包的 security mode 数据(这里的 security mode 没有在三条消息之中,所以不受 mic 签名的保护,中间人可随意修改):

中间人发给服务器的 security mode 数据:

阻止 relay 攻击的方法
session key 进行签名或加密
如果会话阶段要求签名,那么会话阶段将依赖计算新的 session key 并派生其他密钥,来确保会话数据包的完整性。
然而,这个 session key 是客户端和服务器端各自独立计算出一个相同的、对称的密钥。
如果服务器要求使用 session key 派生的密钥加密或签名后续的 http、smb 协议的通信内容,那么 relay 攻击将失效
- 原因:攻击者无法计算出签名依赖的 session key 。
- 结果:即使我们能通过身份验证过渡到会话阶段,但是无法发送正确签名的数据包,服务器拒绝。
我们后续利用 CVE-2019-1040:ntlm mic 签名绕过这一漏洞来绕过以上这一限制,使得会话阶段服务器不校验签名。
我们之前说过 mic 签名本身不会影响中继攻击,真正影响中继攻击的是会话阶段引入签名的这一机制。
我们可以修改协商消息的标志位让服务器在会话阶段禁用签名。
但是此标志为受 mic 签名保护,所以要使用 CVE-2019-1040 来绕过。
- Disabled:这意味着不管理签名(基本上这个选项没了)
- Enabled:此选项表示机器设置了有签名的能力,但不是必须要签名
- Required:表示机器通信时需要签名,否则宁愿不通信
选项存在于注册表 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanmanServer\Parameters 下的
- enablesecuritysignature
- requiresecuritysignature

ok,理论成功我们进行实验
实验 2:需要签名的第三方协议是否能 relay
第一步
- 将服务器 A 的 enablesecuritysignature 和 requiresecuritysignature 设置为 1。
- 将用户 B 的 enablesecuritysignature 和 requiresecuritysignature 设置为 1。
第二步:
攻击者攻击:python3 ntlmrelayx.py -t smb://192.168.72.174 -c ipconfig -smb2support
受害用户受害:dir \\192.168.72.162\c$
第三步:wireshark查看(我已经将包抓下来了,前两步可跳过)
wireshark输入,表示只看有关攻击者的数据包
smb2 && (ip.src==192.168.72.162 || ip.dst==192.168.72.162) && (ip.src != 192.168.72.159) && (ip.dst != 192.168.72.159)
第四步:观察攻击者发送的协商请求数据包
攻击者发送协商请求,希望不要会话阶段进行签名,如下图,要点
- 攻击者发送的协商请求数据包
- security mode 的 enabled 和 required 都设为 0,表示不希望会话阶段进行签名

第五步:观察服务器响应的协商请求数据包
服务器表明,会话阶段必须要签名,否则不进行通信,如下图,要点:
- 服务器返回的协商请求
- security mode 的 enabled 和 required 都设为 1,表明,会话阶段必须要签名,否则不进行通信

第六步:观察会话阶段攻击者的请求
会话阶段,服务器发送的请求没有签名,我们之前讲过原因,如下可看到攻击者发送的请求的签名 Signature 为0000000000000000000000

第七步:观察服务器的响应
可以看到,拒绝服务

同时观察攻击者脚本回显信息:

显然,服务端验证了签名并进行了阻止。
重放到 ldap
域环境中,通过 ldap 协议访问活动目录数据库,而且支持 NTLM 认证,所以我们可以将其他协议 relay 到 ldap 协议。
- http 协议 relay 到 ldap 协议,会话阶段不需要签名,攻击成功。
- smb 协议 relay 到 ldap 协议,会话阶段需要签名,攻击将失败。(解决方法:CVE-2019-1040 漏洞篡改访问 smb 服务时 NTLM身份验证阶段的协商消息中的标志位。)
动目录数据库,而且支持 NTLM 认证,所以我们可以将其他协议 relay 到 ldap 协议。
- http 协议 relay 到 ldap 协议,会话阶段不需要签名,攻击成功。
- smb 协议 relay 到 ldap 协议,会话阶段需要签名,攻击将失败。(解决方法:CVE-2019-1040 漏洞篡改访问 smb 服务时 NTLM身份验证阶段的协商消息中的标志位。)
出现以上差异的原因是,客户端访问 smb 服务开启了会话签名(通常是域环境的默认策略),所以攻击者诱使用户发过来的协商消息的标志位明确要使用会话签名。然而客户端访问 http 服务比较宽松,没有启用相关标志位。
2316

被折叠的 条评论
为什么被折叠?



