CVE-2020-1472 NetLogon 权限提升漏洞

漏洞背景

在2020年8月份微软发布的安全公告中,有一个十分紧急的漏洞——CVE-2020-1472 NetLogon
权限提升漏洞。通过该漏洞,未经身份验证的攻击者只需要能访问域控的135端口即可通过 NetLogon
远程协议连接域控并重置域控机器的Hash,从而导致攻击者可以利用域控的机器账户导出域内所有用户的Hash(域控的机器账户默认具有DCSync权限),进而接管整个域。该漏洞存在的原因是Netlogon协议认证的加密模块存在缺陷,导致攻击者可以在没有凭据的情况下通过认证。通过认证后,调用NetLogon协议中RPC函数NetrServerPasswordSet2
来重置域控机器账户的 Hash,从而接管全域。

漏洞原理

该漏洞由Secura的安全研究员Tom Tervoort以及国内安全研究员彭峙酿、李雪峰发现。 Tom Tervoort
发布了关于该漏洞的详细原理和利用方式的白皮书,并将其名为ZeroLogon。下面分析NetLogon服务运行的流程和造成该漏洞的原因。

1、NetLogon服务

NetLogon服务为域内的身份验证提供一个安全通道,在被用于执行与域用户和机器身份验证相关的各种任务,最常见的是让用户使用NTLM协议登陆服务器。默认情况下,Netlogon
服务在域内所有机器后台运行,该服务的可执行文件路径为 C:\Windows\system32\lsass.exe,如图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TCYL9fkM-1691677486284)(https://image.3001.net/images/20230508/1683552257_6458f8019800ed76dd643.png!small)]

2、Netlogon 认证流程

Netlogon 客户端和服务端之间通过Microsoft Netlogon Remote Protocol(MS-NRPC)来进行通信。MS-
NRPC并没有使用与他RPC相同的解决方案。在进行正式通信之前,客户端和服务端之间需要进行身份认证并协商出一个Session
Key,该值用于保护双方的后续的RPC通信流量。

简要的NetLogon认证流程如图所示:

图片.png

1) 由客户端启动网络登录会话,客户端调用NetrServerReqChallenge函数给服务端发送随机的8字节的Client Challenge值。2)服务端收到客户端发送的NertServerReqChallenge函数调用指令后,服务端也调用NertServerReqChallenge函数发送随机的8字节的Server
Challenge值。3)此时,客户端和服务端均收到了来自对方的 Challenge
值,然后双方都是用共享的密钥secret(客户端机器账户的Hash)以及来自对方的Challenge值通过计算得到Session Key[Session
Key=KDF(secert,(Client Challenge+Server Challenge))]。此时,客户端和服务端均拥有了相同的Client
Challenge、Server Challenge、Session Key。4)客户端使用Session Key 作为密钥加密Client Challenge 得到 Client Credential
并发送给服务端。服务端收到客户端发来的Client Credential后本地使用Session Key 作为密钥私密加密 Client Challenge
计算出Client Credential,然后比较本地计算出的Client Credential和客户端发送来的Client
Credential是否相同。如果两者相同,则说明客户端拥有正确的凭据及Session Key。5)服务端使用Session Key 作为密钥加密Server Challenge得到Server
Credential并发送给客户端。客户端收到服务端发来的Server Credential后,本地用Session Key 作为密钥加密Server
Challenge计算出Server Credential,然后比较本地计算出的Server Credential和从服务端发送来的Server
Credential是否相同。如果两者相同,则说明服务端相同的Session Key。6)至此,客户端和服务端双方互相认证成功并且拥有相同的Session Key,此后使用Session Key来加密后续的RPC通信流量。

到底是以上哪步出现了问题导致漏洞的产生呢?前两步中的Client Challenge 和 Server Challenge
分别是客户端和服务端随机化生成的8字节Challenge值,这里并没有问题,来看看后面几步。

(1)Session Key的生成第3步中的Session Key 是如何加密生成的呢?查看官方文档得知有三种加密算法可供选择,分别为AES、Strong-
key和DES。具体使用哪种加密算法由客户端和服务端协商决定。由于目前版本的WindowsServer 默认都会拒绝的DES和Strong-key加密方案,因此都是协商使用AES进行加密。

客户端和服务端协商使用AES加密后,后续会采用HMAC-SHA256算法来计算Session Key,关于SessionKey 的生成可以阅读以下图片

图片.png

从官方文档可以得知具体的计算机流程如下:* 使用MD4加密算法对共享密钥的Unicode字符串进行散列得到M4SS* 以M4SS为密钥采用HMAC-SHA256算法对Client Challenge和Server Challenge进行一系列运算得到Session Key* 最终取 Session Key 的 低 16 个字节(128位)作为最终的Session Key。

(2)Credential生成再来看看第4、5中的Credential是如何生成的。

查看官方文档得知有两种加密算法可供选择:AES和DES。具体使用哪种加密算法由客户端和服务端协商决定。由于目前版本的Windows
Server默认都拒绝DES加密方案,因此都是协商使用AES进行加密。

图片.png

客户端和服务端协商使用AES加密后,后续会采用AES-128加密算法在8位CFB模式下(也就是AES-CFB8)计算得到Credential。

现在来看看AES-CFB8加密过程:

图片.png

如图所示,首先初始化一个16字节的IV并用Session
Key对其进行AES加密,得到的结果中的第一个字节与8字节的明文input(其实就是Challenge)的第一个字节进行异或运算,将异或的结果放在IV末尾,IV整体向前移一个字节,得到新的IV。然后重复上诉加密、异或、放末尾、移位步骤,直至将所有的明文input加密完毕,得到密文output,密文output与明文input长度相同。

接下来说一说具体加密流程:* IV:fab3c65326caafc0cacb21c3f8c19f68* 明文input:0102030105060708

第一轮加密:AES(fab3c65326caafc0cacb21c3f8c19f68)=e2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx第一个字节e2与明文input第一个字节01进行异或运算得到e3,此时IV变成了b3c65326caafc0cacb21c3f8c19f68e3

第二轮加密:AES(b3c65326caafc0cacb21c3f8c19f68e3)=9axxxxxxxxxxxxxxxxxxxxxxxxxxxxxx第一个字节9a与明文input的第二个字节02进行异或运算得到98,此时IV变成了c65326caafc0cacb21c3f8c19f68e398

以此类推,经过8轮加密后,密文output为e398f5934212f0ba

从以上流程可以看出,为了完成对明文input的各个字节数据的加密,需要指定一个IV来引导整个过程。IV必需具备随机性,这样对于同一个input才能产生不同的加密结果。问题就在于微软在实现该过程中的IV并不是随机生成的,而是固定值。

3、漏洞产生的原因

NetLogon的官方文档MS-NRPC如图所示,可以看到微软使用的是Compute-NetLogonCreadential函数来生成Credential。

图片.png

在ComputeNetLogonCreadential函数中将IV初始化为全0的16字节数据,这就导致了AES-
CFB8算法出现了漏洞。在认证的过程中计算出的Session
Key是随机的,那么对全为0的IV有1/256的概率使得output也全为0。由于NetLogon协议对机器账户的认证次数没有没有限制,因此攻击者可以不断尝试来通过身份认证。

如图所示,对全为0的IV有一定概率导致output也全为0

图片.png

接下来具体说明漏洞产生的具体流程:

假设IV和明文input全为0* IV:00000000000000000000000000000000000* 明文input:00000000000000

第一轮加密:AES(00000000000000000000000000000000000)=00000000000000000000000000000000000第一个字节00与明文00的第一个字节00进行异或运算得到00,此时IV不变,还是00000000000000000000000000000000000

第二轮加密:AES(00000000000000000000000000000000000)=00000000000000000000000000000000000第一个字节00与明文00的第二个字节00进行异或运算得到00,此时IV不变,还是00000000000000000000000000000000000

以此类推,经过8轮加密后,密文output为00000000000000

以上是一中理想状况,假设存在一个Session Key,使得其对全为0的IV进行AES运算的结果的第一个字节为0.但在实际情况中,Session
Key是随机生成的,而用随机生成的Session Key 对全为0的IV进行AES运算的结果第一个字节为0的概率为1/256

在实际的脚本中,安全研究员正是通过控制明文input的值来匹配输出全为0的Session Key,从而通过认证的。

4、绕过签名校验

还有一个需要注意的细节,在认证通过后,后续客户端和服务端通信的流量都是通过Session
Key进行加密的,而安全研究员是通过密文output输出为全为0来绕过认证的。因此,安全研究员并不知道Session
Key的值,自然也就无法对后续的通信流量进行加密。但是通过查看官方文档可知,可以通过取消设置的标志位来关闭这个签名,即通过设置Flags为0x212fffff来关闭签名。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值