Kerberos 认证过程详细分析(一)

此文于2022年1月28日更新。

利用Wireshark 解密 Kerberos 的加密字段 参考

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
#域控导出ntds.dit和system.hive
vssadmin create shadow /for=C:
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\NTDS\NTDS.dit C:\ntds.dit
copy \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy1\Windows\System32\config\SYSTEM C:\system.hive
vssadmin delete shadows /all
git clone https://github.com/csababarta/ntdsxtract.git
cd ntdsxtract/ && python -m pip install pycryptodome
#kali esedbexport ,ntds.dit和system.hive 同目录
esedbexport ntds.dit
python dskeytab.py ntds.dit.export/datatable.4 ntds.dit.export/link_table.6 system.hive ./ 1.keytab
#获取到1.keytab后,把该文件导入到Wireshark的KRB5协议下,并勾选"Try to decrypt Kerberos blobs"
#加载完keytab文件后,wireshark会自动对当前的数据包进行解密尝试,如果解密成功,就会是显示蓝色,不成功就是黄色。

#简介

Kerberos 是由麻省理工学院提出的一种网络身份验证协议。它旨在通过使用密钥加密技术为客户端/服务器应用程序提供强身份验证。Kerberos 协议有两个基础认证模块:AS_REQ & AS_REP 和 TGS_REQ & TGS_REP 。微软扩展了两个认证模块S4U 和 PAC 。

本文着重分析AS_REQ & AS_REP 、 TGS_REQ & TGS_REPAP_REQ & AP_REP 三个过程的数据包,以此来了解Kerberos 的通信与认证过程。

下面以administrator 用户访问域控OWA2013.rootkit.org的CIFS 服务为例。抓包分析该过程。 Rubeus

1
2
3
4
5
6
#请求TGT
Rubeus.exe asktgt /user:"administrator" /password:"admin!@#45" /domain:rootkit.org /dc:"OWA2013.rootkit.org" /nowrap
#请求ST
Rubeus.exe asktgs /service:"cifs/owa2013.rootkit.org" /dc:owa2013.rootkit.org /ptt /ticket:前面的TGT票据
#访问服务
dir \\owa2013.rootkit.org\c$ 

所有数据包如下:

#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,预身份认证,每个认证消息有typevalue
    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-REQUESTPAC扩展
    	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 snamekrbtgt,类型是KRB_NT_SRV_INST
    till: 到期时间,rubeuskekeo都是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 的请求流程

  1. 用户发起AS_REQ,KDC从AS-REQ 请求中取出cname字段并查询活动目录,找到sAMAccountName属性为cname字段的值的用户,用该用户的身份生成一个对应的PAC。用户也可以指定include-pac: False/True来要求KDC在返回的票据中是否包含PAC。

  2. 用户发起TGS_REQ,KDC收到TGT后,利用krbtgt密钥对其解密并验证PAC的签名。签名正确,则证明PAC未经过篡改,然后在PAC的尾部重新生成两个签名: Server Signature (要请求的服务的hash生成的签名)和KDC Signature。然后把新的PAC 拷贝到ST服务票据中。(此步骤不校验PAC 中用户有没有访问服务的权限,只要TGT 正确就返回ST票据)

    如果是S4u2Self请求的话,ST服务票据中的PAC是重新生成的(生成的是模拟用户的PAC)。

  3. 用户拿着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 内容大致相同(不完全相同)。

下文分析委派的抓包与原理。

#参考

https://daiker.gitbook.io/windows-protocol/kerberos

加载评论