此文于2022年1月28日更新。
利用Wireshark 解密 Kerberos 的加密字段 参考
|
|
#简介
Kerberos 是由麻省理工学院提出的一种网络身份验证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证。Kerberos 协议有两个基础认证模块:AS_REQ & AS_REP
和 TGS_REQ & TGS_REP
。微软扩展了两个认证模块S4U 和 PAC 。
本文着重分析AS_REQ & AS_REP
、 TGS_REQ & TGS_REP
和 AP_REQ & AP_REP
三个过程的数据包,以此来了解Kerberos 的通信与认证过程。
下面以administrator 用户访问域控OWA2013.rootkit.org
的CIFS 服务为例。抓包分析该过程。 Rubeus
|
|
所有数据包如下:
#AS 请求分析
#AS_REQ
用户输入账号密码访问域内的服务,本机会向KDC的AS 认证服务发送一个AS_REQ请求。
请求主要包含用户Hash 加密的时间戳、请求用户名、协商Hash的加密类型等信息。
-
整体请求内容
1 2 3 4
1.pvno kerberos的版本号 2.msg-type 消息类型,这里就是KRB_AS_REQ(0x0a) 3.PA_DATA Pre-authentication Data,预身份认证,每个认证消息有type和value。 4.req-body 请求体
-
PA_DATA
1 2 3 4 5 6 7 8 9
PA-DATA PA-ENC-TIMESTAMP 用户HASH加密后的时间戳 padata-type: padata类型 padata-vaule: padata的值 etype: 加密类型 cipher: 加密后的值 PA-DATA PA-PAC-REQUEST:PAC扩展 padata-type: padata类型 padata-vaule: padata的值 include-pac: 是否包含PAC,如果包含那么在响应包中就会返回PAC
-
req-body
1 2 3 4 5 6 7 8
padding:填充 kdc-options:用于与KDC约定一些选项设置 cname: 客户端用户名 realm: 域名 sname: 服务端用户名,在AS_REQ 中sname是krbtgt,类型是KRB_NT_SRV_INST till: 到期时间,rubeus和kekeo都是20370913024805Z,可以作为特征检测 nonce:随机生成的一个数,用于检测重放攻击 etype: 协商加密类型,KDC按照etype类型选择用户hash对应的加密方式
kdc-options 字段
#AS_REP
KDC 收到请求后,通过活动目录查询到该用户的密码Hash,用该Hash对请求包的PA-ENC-TIMESTAMP
进行解密。解密成功后,还会检查要求时间戳的范围在五分钟内且数据包无重放,则预认证成功。
返回krbtgt 用户的NTLM Hash加密后的TGT和用户NTLM Hash加密的Login Session key(AS 随机生成)。
TGT 主要包含Login Session Key、时间戳和 PAC。Login Session Key的作用是作为用户和KDC后几个阶段之间通信加密的会话密钥。
-
整体响应内容
1 2 3 4 5 6
pvno: kerberos的版本号 msg-type: 消息类型KRB-AS-REP crealm: 域名 cname: 客户端用户名 ticket: 即TGT票据 enc_part: 这部分是用用户密码Hash加密的,里面包含Login session key
-
ticket
1 2 3 4
tkt-vno: TGT 版本号 realm: 域名 sname: 请求的服务名称 krbtgt enc-part: 这部份是用krbtgt的密码Hash加密的,其中包含了请求用户的PAC信息
解密enc-part部分,其中
e8e1f426
开头的值就是Login session key。1 2
key: 就是Login session key authorization-data: 里面是PAC的内容,此处不细说PAC ,后文分析。
-
enc_part
内容是由用户密码Hash加密的Login session key。
#TGS 请求分析
#TGS_REQ
用户通过AS_REP拿到TGT票据,并用自己的Hash 解密获得Login session key。再用Login session key 加密客户端用户名、时间戳等信息,和TGT 一起向KDC 的TGS 服务发起请求,请求服务票据。(这一步不需要账号或者密码。主要以TGT 作为凭证)
-
整体请求内容
1 2 3 4
pvno: kerberos的版本号 msg-type: 消息类型 padata: 这个部分包含之前的TGT票据,以及Login session key 加密的内容 req-body: 请求体
-
padata
1 2 3 4
AP_REQ: 这部分会携带AS_REP里面获取到的TGT票据、客户端的认证信息 ... 省略一些前面说过的字段 ticket: 可以看到这部分就是TGT票据 authenticator: 如下图,这部分就是Login session key加密的客户端信息: 请求的用户名、时间戳
可以看到是由Login session key(
e8e1f426
开头的值)解密出来的。 -
req-body
1 2 3 4
...省略介绍过的内容 cname: 请求的用户名 sname: 请求的指定服务 etype: 支持的加密类型
#TGS_REP
TGS 服务收到请求后,使用 Login session key 对authenticator 解密,获取到请求的用户名和时间戳。并检查时间戳在5分钟的有效范围内。KDC 使用krbtgt 用户的hash解密TGT 票据,把解密后的用户名等信息与authenticator 解密后的内容比对,相同则认证通过,颁发服务票据。
返回服务票据(ST)与Login session key加密的Server Session key和请求的服务名称。
服务票据(ST)中包含Server Session key、客户端名称、票据有效时间、PAC 等信息。
-
整体响应内容
1 2 3
...省略介绍过的内容 ticket: 这个是服务票据ST,它由服务账号的Hash加密 enc-part: Login session key加密的Server Session key等信息
-
ticket
字段前面都介绍过,这里不再多说。下面解密enc-part内容,使用
OWA2013$rootkit.org
服务账号Hash解密,内容如下1 2
key: 这里b808087f开头的key就是Server Session key authorization-data: 是用户的PAC,后文细讲
-
enc-part
如下是enc-part 解密后的字段。可以看到依旧是用
e8e1f426
开头的Login session key 解密出来的,并且Server Session key 和 ST 票据中的相同。
#Server 请求分析
#AP_REQ
用户解密Login session key 解密的内容,获得Server Session key 。然后把用户名、时间戳等信息用Server Session key 加密,同服务票据(ST)发送给目标服务。
Tips: 注意本篇文章的的第一张图中,截取了访问域控 CIFS 服务的所有Kerberos请求包。细心点的人就会发现竟然有两次TGS 请求。当我第一次看到为什么会有两次TGS 请求的时候也很疑惑,但这里先不说,可以暂时忽略第二次TGS 请求。等到了后面讲非约束委派的时候就揭晓答案了。
-
整体请求内容
-
跟进Kerberos 协议
1 2
ticket: 这里的ticket字段就是ST票据的内容 authenticator: 就是Server Session Key加密的客户端信息
解密ticket,可看到和之前的ST 票据一样。
可看到使用
b808087f
开头的Server Session Key 解密 authenticator
#AP_REP
服务器会收到用户发来的ST 后,用自己的Hash 解密获得Server Session Key。再用该Key 解密被加密的客户端信息(请求的用户名、时间戳等),并进行校验以及与ST 中的客户端信息进行比对,相同则认证通过。
下图是服务器的SMB响应包
#PAC
PAC (Privilege Attribute Certificate,特权属性证书),其中所包含的是各种授权信息,例如用户RID,所属组的RID、所属组的个数等信息。
前面TGT 票据和ST 票据中的authorization_data
字段一直没有解释。其实这个字段里的内容就是PAC。如果除开该字段,Kerberos 协议就仅能证明用户身份,无法表示用户权限。为此微软引进了此字段来表示用户权限。
有PAC 的请求流程
-
用户发起AS_REQ,KDC从AS-REQ 请求中取出cname字段并查询活动目录,找到
sAMAccountName
属性为cname字段的值的用户,用该用户的身份生成一个对应的PAC。用户也可以指定include-pac: False/True
来要求KDC在返回的票据中是否包含PAC。 -
用户发起TGS_REQ,KDC收到TGT后,利用krbtgt密钥对其解密并验证PAC的签名。签名正确,则证明PAC未经过篡改,然后在PAC的尾部重新生成两个签名: Server Signature (要请求的服务的hash生成的签名)和KDC Signature。然后把新的PAC 拷贝到ST服务票据中。(此步骤不校验PAC 中用户有没有访问服务的权限,只要TGT 正确就返回ST票据)
如果是
S4u2Self
请求的话,ST服务票据中的PAC是重新生成的(生成的是模拟用户的PAC)。 -
用户拿着ST 票据去请求服务,服务使用hash解密ST 票据,获取PAC 后检查用户的sid以及所在的组并并与自身的ACL进行对比,判断用户是否有访问服务的权限。(如果服务开启了验证PAC 的签名,还会向KDC 发送
KERB_VERIFY_PAC
验证PAC 的签名)
只要TGT 票据中不带有PAC,那么ST 票据中也不会带有PAC,也就没有权限访问任何服务。
TGT 中的 PAC 内容
AD-IF-RELEVANT
元素是最外层的包装器,它封装了另一个AD-WIN2K-PAC
类型的AuthorizationData
元素。ad-data
为一段连续的空间。段空间包含一个头部PACTYPE
以及若干个PAC_INFO_BUFFER
。头部PACTYPE
包括cBuffers、Version与缓冲区。
PAC_INFO_BUFFER
为key-value型,key 的类型如下表所示(key对应上图中红色下划线的值)此表参考类型 意义 0x00000001 登录信息。PAC结构必须包含一个这种类型的缓冲区。其他登录信息缓冲区必须被忽略。 0x00000002 凭证信息。PAC结构不应包含多个此类缓冲区。第二或后续凭证信息缓冲区在接收时必须被忽略。 0x00000006 服务器校验和。PAC结构必须包含一个这种类型的缓冲区。其他登录服务器校验和缓冲区必须被忽略。 0x00000007 KDC校验和。PAC结构必须包含一个这种类型的缓冲区。附加的KDC校验和缓冲区必须被忽略。 0x0000000A 客户名称和票证信息。PAC结构必须包含一个这种类型的缓冲区。附加的客户和票据信息缓冲区必须被忽略。 0x0000000B 受约束的委派信息。PAC结构必须包含一个S4U2proxy请求的此类缓冲区,否则不包含。附加的受约束的委托信息缓冲区必须被忽略。 0x0000000C 用户主体名称(UPN)和域名系统(DNS)信息。PAC结构不应包含多个这种类型的缓冲区。接收时必须忽略第二个或后续的UPN和DNS信息缓冲区。 0x0000000D 客户索取信息。PAC结构不应包含多个这种类型的缓冲区。附加的客户要求信息缓冲区必须被忽略。 0x0000000E 设备信息。PAC结构不应包含多个这种类型的缓冲区。附加的设备信息缓冲区必须被忽略。 0x0000000F 设备声明信息。PAC结构不应包含多个这种类型的缓冲区。附加的设备声明信息缓冲区必须被忽略。
其中最重要的就是0x00000001 KERB_VALIDATION_INFO
,也就是上图中的Type: Logon Info (1)
。这个结构是登录信息,主要靠它来验证用户身份。Type: Logon Info (1)
内容如下
其次,抓包发现 ST 中的PAC 和 TGT 中的PAC 内容大致相同(不完全相同)。
下文分析委派的抓包与原理。