轩辕三官 发布于2022年11月8日 分享 发布于2022年11月8日 0x00 前言 在之前的文章《渗透基础——通过LDAP协议暴力破解域用户的口令》中介绍了通过LDAP协议暴力破解域用户密码的方法,最大的特点是会生成一个日志(4625-An账号登录失败)。 但是使用Kerberos预授权暴力破解时,会没有日志(4625-An账号登录失败),所以我对Kerberos做了进一步的研究,用python实现了同样的功能,增加了支持TCP协议和NTLM哈希的验证。本文将记录我自己的研究过程和学习经历。 0x01 简介 Brute简介 野蛮原则 使用python实现Kerberos的细节 开源代码pyKerbrute Kerberos预授权暴力的检测 0x02 kerbrute的适用场景 适用场景:从域外对域用户进行用户枚举和密码暴力破解。 由于没有域用户的密码,LDAP协议无法枚举所有域用户,在LDAP协议进行暴力破解时会产生一个日志(4625-An账号登录失败)。 使用Kerberos有以下优点: 使用Kerberos预授权强制更快。 不会生成日志(4625-帐户登录失败) 注: 默认情况下,Kerberos-auth对应的端口是88。 0x03 kerbrute测试 测试环境如下 Kerbrute是用Go语言开发的,github提供编译后的文件,地址如下: https://github.com/ropnop/kerbrute/releases Kerbrute主要包括以下两个函数: 1.用户枚举 用于验证用户是否存在,命令如下: kerbrute _ windows _ amd64 . exe userenum-DC 192 . 168 . 1 . 1-d test.com user . txt 测试结果如下 适用场景: 你不知道域用户的密码,所以你不能通过LDAP协议枚举所有域用户。您可以使用这种方法来验证用户的存在。 2.口令验证 确认用户存在后,可以使用该功能验证密码是否正确。该命令如下所示: kerbrute _ windows _ amd64 . exe passwordspray-d test.com user . txt domain user 123! 测试结果如下 如果登录成功,将生成一个日志(4768-请求了一个Kerberos身份验证票(TGT )),如下图所示 0x04 使用python实现kerbrute的细节 我的想法是实现kerbrute的两个主要功能:用户枚举和密码验证。 我在通过python实现kerberos协议的部分参考了pykek。 接下来,通过捕获包获得kerbrute的包的内容,然后用python构造相同的包。 Kerbrute使用UDP协议实现Kerberos预授权,用于验证明文密码。 在我研究的过程中,我发现同样的功能可以通过TCP协议实现,NTLM哈希也可以验证。 1.使用python实现用户枚举 使用wireshark捕获kerbrute用户枚举函数生成的数据包。 使用UDP协议,枚举用户时发送的数据包内容如下 如果用户存在,返回的数据包内容如下 标记:错误代码:err-preauth-required (25) 如果用户不存在,返回的数据包内容如图所示。 标记:错误代码:err-c-principal-unknown (6) 接下来就是用python发送UDP数据,和kerbrute用户枚举时的数据包一样。接收内容,通过标志位判断用户是否存在。 同样的功能可以通过TCP协议实现,只是数据包格式不同。 应该在TCP数据包之前添加一个字符串包(' I ',len(data))。 具体代码如下: TCP: def send_req_tcp(req,kdc,port=88): 数据=编码(请求) data=pack('I ',len(data))数据 sock=socket.socket(socket。AF_INET,socket。袜子_流) sock.connect((kdc,port)) sock.send(数据) 回力袜 def recv_rep_tcp(sock): 数据=' ' datalen=无 虽然正确: rep=sock.recv(8192) 如果不是代表: sock.close() 引发IOError(“连接错误”) 数据=代表 如果len(rep)=4: 如果datalen为None: datalen=unpack('I ',rep[:4])[0] 如果len(data)=4 datalen: sock.close() 返回数据[4:4数据长度] UDP: def send_req_udp(req,kdc,port=88): 数据=编码(请求) sock=socket.socket(socket。AF_INET,socket。SOCK_DGRAM) sock.connect((kdc,port)) sock.send(数据) 回力袜 def recv_rep_udp(套接字): 数据=' ' datalen=无 虽然正确: rep=sock.recv(8192) 如果不是代表: sock.close() 引发IOError(“连接错误”) 数据=代表 如果len(rep)=4: sock.close() 返回数据 2.使用python实现口令验证 使用wireshark捕获kerbrute密码验证函数生成的数据包。 使用UDP协议时,口令验证过程中发送的数据包内容如图所示。 与用户枚举相比,密码验证中有更多的内容(padata)。 具体区别如下: 枚举用户发送的数据包格式如下 密码验证发送的数据包格式如下 因此,在实现中需要添加padata段的内容。 如果密码正确,返回的数据包的内容如下 如果密码错误,返回的数据包内容如下 具体的包结构请参考RFC文档,地址如下: https://tools.ietf.org/html/rfc1510#page-50 要计算padata-value,需要在计算前将明文密码转换为NTLM哈希。 因此,这个位置不仅可以使用明文密码,还可以使用NTLM哈希。 加密python代码的一部分如下: 使用明文密码: clearpassword=DomainUser123! user_key=(RC4_HMAC,ntlm _哈希(clearpassword)。digest()) pa_ts=build_pa_enc_timestamp(当前时间,用户密钥) as _ req[' padata '][0][' padata-value ']=encode(pa _ ts) 使用NTLM哈希: NTLM hash=e 00045 BD 566 a1 b 74386 F5 C1 e 3612921 b user_key=(RC4_HMAC,ntlmhash.decode('hex ')) pa_ts=build_pa_enc_timestamp(当前时间,用户密钥) as _ req[' padata '][0][' padata-value ']=encode(pa _ ts) 0x05 开源代码pyKerbrute 的完整实现代码已上传至github,地址如下: https://github.com/3gstudent/pyKerbrute Kerbrute是kerbrute的python实现。与Kerbrute相比,它有以下两个功能: 添加对TCP协议的支持 添加NTLM哈希验证。 PyKerbrute有两个功能:用户枚举和密码验证。 1.EnumADUser.py 用户枚举功能,支持TCP和UDP协议 命令示例: test.com用户 输出如下所示 2.ADPwdSpray.py 密码验证功能,支持TCP和UDP协议,明文密码和NTLM哈希。 示例1: adpwdspray . py 192 . 168 . 1 . 1 test.com user . txt clear password域用户123!传输控制协议 输出如下所示 示例2: adpwdspray . py 192 . 168 . 1 . 1 test.com user . txt NTLM hash e 00045 BD 566 a1 b 74386 F5 c1e 3612921 b UDP 输出如下所示 0x06 Kerberos pre-auth bruteforcing的检测 Kerberos使用Kerberos预授权协议,并且不生成日志(4625-帐户登录失败) 但是,将生成以下日志: 密码验证成功时生成日志(4768-请求了Kerberos身份验证票(TGT)) 密码验证失败时生成日志(4771-Kerberos预验证失败) 0x07 小结 本文对Kerberos进行了测试和分析,用python实现了相同的功能,并增加了支持TCP协议和NTLM哈希的验证,开源代码。介绍了脚本编写的细节,并给出了Kerberos预授权暴力的检测方法。 留下回复 链接帖子 意见的链接 分享到其他网站 更多分享选项…
推荐的帖子