PAC原理
PAC的全称是Privilege Attribute Certificate(特权属性证书), 其中所包含的是各种授权信息, 例如用户所属的用户组, 用户所具有的权限等。
在Windows的Kerberos实现中, 默认情况下,KRB_AS_REP信息中将包含一组PAC信息, 也就是说, 用户所得到的TGT(TicketGranting Ticket)会包含用户的授权信息。用户再用包含有授权信息的TGT去申请相应的Service Ticket,KDC在收到这个KBR_AP_REQ请求的时候, 将TGT里的PAC信息解析出来, 加入到Service Ticket里返回。接下来, 当用户向服务器程序提交KRB_AP_REQ消息时, 服务器程序则将其中所包含的PAC信息传送给操作系统得到一个访问令牌, 并且同时将这个PAC的数字签名以KRB_VERIFY_PAC的消息传输给KDC, KDC再将验证这个PAC的数字签名的结果以RPC返回码的形式告诉服务器, 服务器就可以根据这个结果判断PAC数据的真实性和完整性,并做出最后对KRB_AP_REQ的判断。
—— 微软
PAC 结构如下:
PAC 结构是 AuthorizationData:
1 |
|
由图可知:
- ad-type 为 AD-IF-RELEVANT
- ad-data 仍然是一个 AuthorizationData,ad-type 为 AD-WIN2K-PAC,ad-data包含一个 PACTYPE 结构以及若干个 PAC_INFO_BUFFER 结构数组。每个 PAC_INFO_BUFFER 定义了 PAC 缓冲区的类型和字节偏移量。PAC_INFO_BUFFER 数组没有定义的顺序。因此,PAC_INFO_BUFFER 缓冲区的顺序没有意义。但是,一旦生成了 KDC 和服务器签名,缓冲区的顺序不得更改,否则 PAC 内容的签名验证将失败。PAC_INFO_BUFFER结构如下:
ulType=0x00000001时:对应结构体为 KERB_VALIDATION_INFO,PAC 结构必须包含一个这种类型的缓冲区,即登录信息:
1 |
|
ulType=0x0000000A 时:对应结构体为 PAC_CLIENT_INFO,其中包含客户端的名称和身份验证时间:
1 |
|
uIType=0x00000006 和 uIType=0x00000007 :
0x00000006 对应的是服务检验和,0x00000007 对应的是KDC校验和。分别由server密码和KDC密码加密,是为了防止PAC内容被篡改。
两个都是 PAC_SIGNATURE_DATA 结构:
1 |
|
微软官方的 PAC 验证过程如下:
- 客户端尝试访问需要Kerberos 身份验证的资源。客户端发送 AP-REQ 向服务器请求认证。
- 服务将PAC传递给操作系统以接收访问令牌。服务操作系统将 AP-REQ 中的 PAC 签名转发给域控制器以在 KERB_VERIFY_PAC 消息中进行验证。
- 域控制器验证响应上的签名并将结果返回给服务器。该错误作为适当的 RPC 状态代码返回。
- 服务器验证AP-REQ,如果验证成功则发送AP-REP。
MS14-068
KERB_VALIDATION_INFO 结构中,GroupIds 包含帐户域中帐户所属的组,如果将域管组的 sid 加入 GroupIds,发送用户的 TGS 去询问域管是否有访问服务的权限的时候,域控会解密PAC,提取用户的 sid 和 GroupId,此时域控会把这个用户当做域管组里面的成员,从而提升为域管。
利用过程
Client 向 KDC-AS 发送伪造的 KRB_AS_REQ
与正常的 KRB_AS_REQ 的区别在于 include_pac 为 false,这个选项是指定身份验证过程中是否需要 PAC 的参与,设置为 false 后,返回的 TGT 就不会包含 PAC
KDC 返回给 Client KRB_AS_RSP
KRB_AS_RSP:Clien hash 加密的 session key,用 KDC hash 加密的 TGT
Client 向 KDC-TGS 发送伪造的 KRB_TGS_REQ
如图,为 KRB_TGS_REQ 结构 5.4.1
KRB_TGS_REQ padata 结构:
padata-value AP-REQ 结构(存放着用 krbtgt hash 加密的 TGT):
REQ-BODY结构:
1 |
|
此时构造 PAC ,PAC 中有两个校验和,分别由server密码和KDC密码加密,理论上规定是必须带有 Hash 的签名算法才行,但是微软在实现上,允许任意算法,而且由客户端指定,这就是 ms14-068 漏洞根本原因之一。因此在伪造时,随机生成一个 subkey,用 sessionkey 加密后,放在 authenticator 中,用 sub-sessionkey 加密 PAC,放在 enc-authorization-data 字段。
KDC-TGS 返回 KRB_TGS_RSP
KDC 从 Authenticator 中提取了 sub-sessionkey,从而解密出 subkey,用 subkey 解密了 PAC,利用客户端设定的签名算法验证了签名。验证成功后,KDC 解密 PAC 的尾部,重新用自己的 server hash 和 kdc hash 生成一个签名,将 server session key 用 subkey 加密,组成一个新的 TGT 返回给 Client。
最终使用这个 TGT 和 server session key 制作的票据就可以达到提权为域管的目的。
复现
-
获取当前域用户 sid:
whoami /all
S-1-5-21-835054697-1105834094-592000501-1106 -
获取域控名:
nslookup -type=SRV _ldap._tcp
-
执行EXP:
MS14-068.exe -u test@hack.com -s S-1-5-21-835054697-1105834094-592000501-1106 -d hack.com
- mimikatz 导入票据:
kerberos::ptc TGT_test@hack.test.ccache
-
查看权限:
PsExec.exe \\win2008-1.hack.com cmd.exe