NTLM Relay 中间人攻击
1 前言
1.1 背景介绍
NTLM Relay
,中间人攻击或重放攻击是一个意思。
B 是一个 smb 服务器,A 来进行认证,B 将 A 的认证信息转发到 C 上,如果 A 的凭证在 C 上认证成功就能进行下一步操作,如创建服务执行命令。如果在域中控制了某些常用服务,如:WEB OA 系统、文件共享等服务则可以尝试使用 SMB 中继攻击来引诱域管理员访问达到获取其他机器权限的目的。
- 2001 年,最早由 Dystic 实现,SMBRelay
- 2004 年,发展为 HTTP -> SMB,BlackHat,未开源
- 2007 年,HTTP -> SMB 被集成到 MetaSploit
- 2008 年,HTTP -> HTTP 的 NTLM 攻击被实现(MS08-067)
1.2 认证过程
两端模型:
三端模型:
在域环境下的 NTLM Relay 的模型:
1.3 HTTP -> SMB 攻击实验
1.3.1 nmap 探测 SMB 签名
nmap 扫描:
nmap -p445 --script=smb-security-mode.nse IP --open
1.3.2 使用 ntmlrelayx.py 测试
ntmlrelayx.py 脚本在 empire 包中
ntlmrelayx.py -tf hosts.txt -socks -smb2support
注意 发起攻击时,HTTP -> SMB,开启 80 端口,需要保证端口未被占用
攻击成功后,会在攻击机本地开启 1080
socks 端口,通过 proxychain
等代理工具,即可控制目标机器。
# mac 下 proxychain-NG
proxychains4 /Users/Geekby/opt/anaconda3/bin/python secretsdump.py pentest.com/Administrator@172.16.147.132
注意 进行认证时会提示输入密码,留空即可使用 relay
后的凭据进行认证。
1.4 Hot Potato
Hot Potato 是一个经典的利用 NTLM Relay 获取高权限用户控制权的例子,可以参考「Potato 家族提权分析」这篇文章。
1.5 NTLM Relay 防御
目前有许多针对 NTLM
重放攻击的防御措施,主要包括以下几种:
- SMB & LDAP 签名
- EAP (Enhanced Protection Authentication)
- LDAPS Channels
- Server target SPN Validation
1.5.1 SMB & LDAP 签名
完成认证后,应用服务器和客户端之间的所有流量都有签名验证保护;用户签名的会话密钥基于客户端的 NTLM 值生成,应用服务器在 NETLOGON
阶段从 DC
服务器获取;客户端采用和 DC
相同的算法,基于自身的 NTLM
值生成会话密钥,因此中间人攻击没有办法获取会话密钥
1.5.2 EAP (Enhanced Protection Authentication)
NTLM
认证和一个安全通道进行绑定,在 NTLM
认证过程中,最后的 NTLM
认证数据报文包含一个目标应用服务器的证书摘要,这个摘要使用客户端的 NTLM
值进行签名保护,可以防止伪造证书的攻击。
1.6 关于 NTLM 协议的一些总结
NT Hash = md4(unicode(hex(password)))
NTLMv2 Hash = HMAC-MD5(unicode(hex(upper(username+domain))), NT Hash)
NTProofStr = HMAC-MD5(challenge + 数据, NTLMv2 Hash)
Session Key = HMAC_MD5(HMAC_MD5(NTLMv2 Response + Challenge, NTLMv2 Hash), NTLMv2 Hash)
MIC = HMAC_MD5(NEGOTIATE_MESSAGE + CHALLENGE_MESSAGE + AUTHENTICATE_MESSAGE, Session key)
2 CVE-2015-0005
2.1 原理
应用服务器在收到用户客户端的认证信息后,由于本身没有存储用户的口令信息,所以必须依赖域服务器进行认证,将收到的认证信息发送给域服务器,这个过程基于 NETLOGON
协议。该协议在应用服务器和域服务器之间建立一个安全会话,安全会话共享密钥基于应用服务器主机账号的口令 NTLM
生成。
2.1.1 NETLOGON 步骤
均为 RPC 远程向认证服务器调用
- NetrLogonSamLoginEx
NetrLogonSamLogonWithFlags
- NetrLogonSamLogon
- NetrLogonSamLogoff
2.1.2 攻击场景
win10x64en$
上的用户 eviluser
,访问内服务器 win2008R2$
的 SMB
服务,采用 NTLM
认证方式,域服务器为 Win2016-dc01$
,认证过程概括如下:
win10x64en$
首先向win2008R2$
的 SMB 445 端口发起一个连接NTLM_NEGOTIATE
,协商使用NTLM
认证方式;win2008R2$
收到后,发送NTLM CHALLENGE
返回给win10x64en$
;win10x64en$
收到NTLM CHALLENGE
后,向win2008R2$
发送一个NTLM
认证报文;Win2008R2$
和域控服务器之间共享了Win2008R2$
的口令 NTLM,以此生成会话密钥,创建一个NETLOGON
安全会话。Win2008R2$
通过 RPC 调用域服务器的NetrLogonSamLogonWithFlags
函数,并将win10x64en$
发送过来的认证信息加上此前的 挑战信息 全部填装进入作为参数;- 域服务器收到信息后,验证认证信息,如果认证合法则返回
STATUS_SUCCESS
; - 如果
NetrLogonSamLogonWithFlags
调用成功,则应用服务器会返回NETLOGON_VALIDATION
数据结构,该结构的结尾可能是以下结构中的一种:NETLOGON_VALIDATIN_SA_FO
,NETLOGON_VALIDATION_SAM_INFO2
,NETLOGON_VALIDATION_SAM_INFO4
。在这个结构中有一个重要的数据,就是SessionKey
,用于用户客户端和应用服务器之间的签名、加密等;
SessionKey
基于客户端用户的口令NTLM
生成,应用服务器从DC
获取,客户端用户自己采用相同的算法生成,因此应用服务器和客户端不需要交互SessionKey
;
- 第二个参数为主机名(微软的解释 「Computer Name: The Unicode string that contains the NetBIOS name of the client computer calling this method」),主机名为调用该函数的客户端主机名,也就是应用服务器通过 RPC 远程调用的该函数,因此该主机名理论上应该与应用服务器和域服务器之间安全会话密钥的主机账号应该一致。
所以任何一台域内主机,只要能拿到此前用户和应用服务器的认证信息,就可以向域服务器发起 NETLOGON
,从而获取 SessionKey
,这样后面可以伪造应用服务器和客户端用户之间的数据签名,满足中间人攻击。
2.2 实战
利用 impacket 中的 smbrelayx 进行中间人攻击,如果目标机器强制使用 SMB 签名,该模块会使用 NETLOGON 直接获取签名用的 sessionKey
环境:
攻击机(非域内主机) :192.168.68.24
客户端服务器(被中间人攻击的服务器) : SERVER-2008
目标主机、应用服务器 : Windows Server 2012 - 172.16.147.130
信息 如果是非域主机,需要指定当前域内任意一台主机的 hash,且指定域控的 IP。
python2 smbrelayx.py -h 172.16.147.130 -machine-account pentest-ad/SERVER-2008$ -machine-hashes bab7079288e58b875c46601f274001e6:bab7079288e58b875c46601f274001e6 -domain 172.16.147.130
可以使用 -e 参数指定目标机器要执行的文件,不指定的话,默认 dump 下目标机器的 Hash,-c 可以指定要执行的命令。
2.3 防御
影响 Windows Server 2012 及以下,对个人 PC 无影响
微软发布了补丁 MS15-027
,针对这个漏洞进行了修补,对 ComputerName
和 NetBIOS
这 2 个字段进行了校验,并且对这个消息认证块进行了签名校验
3 CVE-2019-1019
在 CVE-2015-0005 漏洞被修补后,域服务器会校验 ComputerName 和 NetBIOS 这 2 个字段是否一致。但是如果 ComputerName 字段缺失,则域服务器会接受,而且不会对认证消息进行完整性校验(MIC) 。
3.1 原理
由于 NTLM_AUTHENTICATION
报文中的很多信息,包括 ComputerName
字段信息,是从 NTLM-CHALLENGE
中拷贝获取,因此在攻击者可以截获由应用服务器发送给客户端的挑战信息,并将 ComputerName
字段进行删除,客户端收到挑战信息后,由于找不到 ComputerName
字段,会导致随后的 NTLM_AUTHENTICATION
也不包含该字段。
通过配置,可以让 NTLM 启用完整性校验,即在认证消息中添加一个字段 MIC(Message Integrity Code)
,在新版本中这是默认开启的功能。 MIC
是用来保护 NTLM 认证报文的完整性,即 NTLM_CHALLENGE
。
MIC
通过基于 SessionKey
会话秘钥的 HMAC_MD5
算法实现完整性保护,而此前的分析中,我们有能力方法获取这个 SessionKey
,因此修改后重新计算 MIC
即可。
客户端发起到应用服务器的
NTLM_NEGOTIATE
,被重放攻击者捕获攻击者将
NTLM_NEGOTIATE
转发给真正的应用服务器,也即我们的攻击目标应用服务器返回一个
NTLM_CHALLENGE
给攻击者重放攻击者将
NTLM_CHALLENGE
中的ComputerName
字段去掉,然后转发给客户端客户端收到修改后的
NTLM_CHALLENGE
,基于这些信息构造NTLM_AUTHENTICATE
,将认证信息发送给重放攻击者,此时认证消息已经包含MIC
重放攻击者向域服务器发起一个
NETLOGON
会话请求,由于认证消息中ComputerName
字段缺失,域服务器不进行完整性校验,认可该认证消息,并返回一个Sessionkey
重放攻击者重新计算
MIC
,并将新的NTLM_AUTHENTICATE
发送给应用服务器应用服务器收到
NTLM_AUTHENTICATE
后,校验MIC
,然后向域服务器发起NETLOGON
会话请求,域服务器返回认证成功的响应,其中包含会话密钥,这个会话密钥和第 6 步中的会话密钥相同重放攻击者成功地与应用服务器建立了一个带签名的会话,获取了客户端用户在应用服务器上的访问权限,如果客户端用户是管理员,而应用服务器是域服务器,则重放攻击者具备了在域服务器(应用服务器) 上的管理员权限(客户端)。
3.2 实战
利用 impacket 中的 ntlmrelayx.py 进行中间人攻击,使用 -remove-target
参数。
python3 ntlmrelayx.py -h 172.16.147.130 -remove-target --enum-local-admins -smb2support -machine-account pentest-ad/SERVER-2008$ -machine-hashes bab7079288e58b875c46601f274001e6:bab7079288e58b875c46601f274001e6 -domain 172.16.147.130
4 CVE-2019-1040
4.1 原理
在安装了 CVE-2015-0005
的补丁后,系统会校验 NetBIOS
的名称和 NetrLogonSamLogonWithFlags
函数的 ComputeName
参数是否相同。因此,此前通过修改 ComputerName
来获取 SessionKey
的方法失效。
但是如果认证信息中的 NetBIOS
被删除或者消失后,认证服务器不会再进行前面的名字校验,也就是说我们再修改 ComputerName
参数,能达成 CVE-2015-0005
漏洞的效果,从而获取会话密钥。
针对这种情况,可以通过配置“服务器拒绝任何没有 NetBIOS 的请求”来阻止此类攻击。但是在 NTLMv1
中,NTLM 消息块结构体中,本来就没有这个字段,因此这种攻击在 NTLMv1
场景中难以通过策略或者补丁来杜绝,仍然存在很大的脆弱性。
客户端和服务器在 NTLM 协商时,通过下图中 NegotiatFlags
(即 msvAvFlags 字段) 来标识是否需要 MIC 来保护会话的完整性,见下图中红色框标识。
SMB 客户端在 NTLM 认证时,默认设置需要 MIC 进行完整性校验保护。直观而言,一般会有几种方式对抗 MIC,一是修改 MIC,前提条件是获取会话密钥,在前面我们看到:如果配置了防护策略,通过删除 NetBIOS 不能获取会话密钥;二是直接丢弃 MIC,这时需要将 msVAvFlags
字段中的标志位同样进行修改,以及版本信息,因为有些版本默认是必须要有 MIC。
msvAvFlags 字段的定义,查看微软知识库,如果为 0x00000002
表示客户端通过 MIC
来保护数据报文的完整性
msvAVFlags
字段由用户的 NTLM 散列值进行签名保护,因此不能修改 msvAVFlag
字段。实际中非常神奇,域服务器并不真正在乎 MIC 和 Version 信息是否存在,如果存在,则校验,如果不存在则不校验。
上述的攻击方式,可以通过配置进行阻止,即如果 msvAVFlags
字段表明有 MIC 完整性校验,就必须要有 MIC 的存在,而且进行校验。但是在实际应用场景中,仍然存在一些隐患,例如 MacOS
、 Linux
系统中的 FireFox
默认情况下,不添加 MIC。
4.2 实战
利用 impacket 中的 ntlmrelayx.py 进行中间人攻击,使用 --remove-mic
参数。
python3 ntlmrelayx.py -h ldap://172.16.147.130 --remove-mic --escalate-user commonuser -smb2support -machine-account pentest-ad/SERVER-2008$ -machine-hashes bab7079288e58b875c46601f274001e6:bab7079288e58b875c46601f274001e6 -domain 172.16.147.130
5 EPA-Bypass
5.1 原理
EPA (Enhanced Protection for Authentication),将认证报文绑定到一个安全通道中,主要用于保护 Windows 集成认证的服务,例如 OWA、ADFS、 LDAPS。
具体的做法是,在认证报文中添加一个字段 Channel Bindings
,根据微软的说明, Channel Bindings
为一段 MD5 Hash
值,表示结构体 gss_channel_bindings_struct
的 MD5Hash
值。
如果启用了 EPA
,在客户端发送的 认证报文 中,会添加一个字段 NTProofStr
,这是一段签名,用来保护 Channel Bindings
。微软给出 NTProofStr
的计算算法如下:
可以得知, NTProofStr
基于用户的 NTLM
值计算得来,因此,在此种攻击场景中不可能计算得出。可以使用 EPA 来保护 ADFS
、 OWA
、 LDAPS
等基于 NTLM
认证的场景。比较悲剧的是,在默认情况下,上述这些服务器都没有强制使用了 EPA
。 NTProofStr
和 Channel Bindings
在实际的报文中见下图,这是一个客户端发送的认证报文。
如果我们在服务器发送挑战信息到客户端时,在挑战报文主动中添加一个 Channel Bindings
到消息块中,类似于下图所示,注意下图是服务器发送的挑战报文,由于 Channel Bindings
是一段 MD5Hash
值,是比较好添加的。
客户端收到挑战信息后,会将我们事先添加的 Channel Bindings
,并且再次计算一个新的 Channel Bindings
添加到认证报文后面,导致认证报文包含 2 个 Channel Bindings
,见下图,注意这是一个客户端发送的认证报文。
在这种情况下,域服务器会选择第一个 ChannelBindings
进行校验,忽略第二个 Channel Bindings
,这样我们就可以规避 EPA
的保护,实现攻击目的。
如果客户端开启了 MIC
保护,则和前面一样,直接丢弃 MIC
参考:
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论