提升权限_CVE20201472 NetLogon 权限提升漏洞研究

本文作者  Strawberry @ QAX A-TEAM

62811cec-ab39-eb11-8da9-e4434bdf6706.gif

CVE-2020-1472 NetLogon 权限提升漏洞是微软8月份发布安全公告披露的紧急漏洞,CVSS漏洞评分10分,漏洞利用后果严重,未经身份认证的攻击者可通过使用 Netlogon 远程协议(MS-NRPC)连接域控制器来利用此漏洞。成功利用此漏洞的攻击者可获得域管理员访问权限。本文对此漏洞进行分析,如有不足之处,欢迎批评指正。

62811cec-ab39-eb11-8da9-e4434bdf6706.gif

声明:本篇文章由 Strawberry @ QAX A-TEAM原创,仅用于技术研究,不恰当使用会造成危害,严禁违法使用 ,否则后果自负。

QAX A-TEAM漏洞简讯

CVE-2020-1472 NetLogon 权限提升漏洞是微软8月份发布安全公告披露的紧急漏洞,CVSS漏洞评分10分,漏洞利用后果严重,未经身份认证的攻击者可通过使用 Netlogon 远程协议(MS-NRPC)连接域控制器来利用此漏洞。成功利用此漏洞的攻击者可获得域管理员访问权限。

协议分析

Netlogon 服务用于维护计算机与对域中的用户和其他服务进行身份验证的域控制器之间的安全通道,Netlogon 客户端和服务端之间通过RPC调用来进行通信。在进行正式通信之前,双方需进行身份认证并协商出一个 SessionKey。SessionKey 将用于保护双方后续 RPC 通信流量。以下为 Netlogon 身份验证握手流程:

68811cec-ab39-eb11-8da9-e4434bdf6706.png

首先由客户端发起挑战(传送Client challenge),服务端响应Server challenge,然后双方都使用共享的密钥以及来自双方的 challenges 进行计算得到 SessionKey,这样双方就拥有了相同的 SessionKey 以及 Client challenge 和 Server challenge。然后客户端使用 SessionKey 作为密钥加密 Client challenge 得到 Client credential 并发送给服务端,服务端也采用相同的方法计算出一个 Client credential,比较这两者是否相同,如果相同,则客户端身份认证成功,然后双方对调来验证服务端的 Server credential,如果成功,则说明双方身份认证成功且拥有相同的 SessionKey,后续可采用该密钥进行加密和完整性保护。

  • SessionKey 计算过程

    如果双方协商了AES support,就会采用 HMAC-SHA256 算法来计算 SessionKey,具体流程如下:

    使用MD4算法对密码的 Unicode 字符串进行散列得到 M4SS,然后以 M4SS 为密钥采用 HMAC-SHA256 算法对 ClientChallenge + ServerChallenge 进行哈希得到 SessionKey,取 SessionKey 的低16个字节作为最终的 SessionKey。

ComputeSessionKey(SharedSecret, ClientChallenge, ServerChallenge) M4SS := MD4(UNICODE(SharedSecret)) CALL SHA256Reset(HashContext, M4SS, sizeof(M4SS)); CALL SHA256Input(HashContext, ClientChallenge, sizeof(ClientChallenge)); CALL SHA256FinalBits (HashContext, ServerChallenge, sizeof(ServerChallenge)); CALL SHA256Result(HashContext, SessionKey); SET SessionKey to lower 16 bytes of the SessionKey;
  • Credential 计算过程

    如果双方协商了AES support,后续会采用 AES-128 加密算法在 8 位 CFB 模式下计算 Credential(来自MS-NRPC文档)。其计算过程大致如下:

    在 ComputeNetlogonCredential 函数中将 IV 初始化为 0,Input 接收 Challenge,使用 IV、SessionKey 对 Input 进行加密,AesEncrypt 使用的算法为 8 位 CFB 模式的 AES-128。

ComputeNetlogonCredential(Input, SessionKey, Output) SET IV = 0 CALL AesEncrypt(Input, SessionKey, IV, Output)

下面来插播一下 AES-CFB8 算法,如下所示:

首先初始化随机 IV(16字节),对 IV 进行 AES 运算,将结果的第一个字节与 PLAINTEXT(可对应上面算法的 Input) 的下一个字节进行异或,将异或结果放在 IV 末尾,IV 整体向前移1位。然后重复上述 "加密->异或->移位" 操作,直到取出了 PLAINTEXT 中的所有字节。最后得到 CIPHERTEXT(对应上面算法的 Output,其长度与 Input 相同)。

6a811cec-ab39-eb11-8da9-e4434bdf6706.png

Netlogon 在计算 Credential 的过程中直接将 IV 初始化为 0,这会使 AES-CFB8  算法出现漏洞,Secura 的研究人员是在阅读 Microsoft 文档时发现了这个安全问题。由于在认证过程中 SessionKey 是随机的,因而对 IV 进行 AES 块加密得到的结果也是随机的,但只取结果中的第一个字节,这个字节为 X 的概率为 1/256(第一个字节可能的结果为 0 ~ 255)。那么我们假设第一轮 IV(全0) 加密结果的第一个字节为 X,我们就知道全 0 的输入可以获得输出 X ,因而我们可以构造 Challenge 为 XXXXXXXY,使得每一次异或的结果都为 0(除了最后一次,最后一位不参与加密运算),那么每一轮的 "IV" 还是全 0 的,每一次加密结果的第一个字节都是 X,这样就可以得到一个确定的 Credential:00 00 00 00 00 00 00 (X Xor Y)。因而在平均 256 次尝试之后,可以成功使用 00 00 00 00 00 00 00 (X Xor Y) 模式的 Credential 欺骗服务器认证通过而无需知道真正的密码以及 SessionKey,POC 中就选择将 X、Y 设置为 0,如下所示:

6c811cec-ab39-eb11-8da9-e4434bdf6706.png

  • Authenticator 认证

    在协商出 SessionKey 后,客户端就可以申请远程调用了,如 POC 中使用的 NetrServerPasswordSet2,这也是简略流程图中的最后一步。除了 NetrLogonSamLogonEx 之外,所有需要安全通道的调用都将使用 Netlogon Authenticator。Authenticator 结构如下所示,包括 8 字节的 Credential 和 4 字节的 Timestamp。

 typedef struct _NETLOGON_AUTHENTICATOR {
       NETLOGON_CREDENTIAL Credential;   DWORD Timestamp; } NETLOGON_AUTHENTICATOR,  *PNETLOGON_AUTHENTICATOR;

    客户端在每次发送新请求时,都会记录当前时间戳(ClientAuthenticator.Timestamp,表示自1970年1月1日(UTC)00:00:00起的秒数),然后更新 ClientCredential(之前的 ClientCredential 加 Timestamp),然后以 SessionKey 为密钥使用之前协商的加密算法计算出 ClientAuthenticator.Credential,之后将 Authenticator 附在调用请求中一起发送给服务端。

SET TimeNow = current time;SET ClientAuthenticator.Timestamp = TimeNow;SET ClientStoredCredential = ClientStoredCredential + TimeNow;CALL ComputeNetlogonCredential(ClientStoredCredential, Session-Key, ClientAuthenticator.Credential);

    服务端接收到请求后将采用相同的步骤计算 TempCredential( ClientCredential 和 SessionKey 是一致的),比较 TempCredential 和 客户端发来的 ClientAuthenticator.Credential 是否一致,一致则通过客户端认证。然后服务端将 ClientCredential 加1之后进行同样的运算,得到 ServerAuthenticator.Credential ,将 Authenticator 附在响应包中。

SET ServerStoredCredential = ServerStoredCredential + ClientAuthenticator.Timestamp;CALL ComputeNetlogonCredential(ServerStoredCredential, Session-Key, TempCredential);IF TempCredential != ClientAuthenticator.Credential THEN return access denied errorSET ServerStoredCredential = ServerStoredCredential + 1;CALL ComputeNetlogonCredential(ServerStoredCredential, Session-Key, ServerAuthenticator.Credential);

    然后客户端更新 ClientCredential(自加1),进行同样的运算得到 TempCredential ,判断 TempCredential 和服务端发来的 ServerAuthenticator.Credential 是否一致,一致则通过认证,否则重新建立安全通道。

SET ClientStoredCredential = ClientStoredCredential + 1;CALL ComputeNetlogonCredential(ClientStoredCredential, Session-Key, TempCredential);IF TempCredential != ServerAuthenticator.Cr
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值