MS14068
MS14068 是一个能够使普通用户提权到域控权限的权限提升漏洞。攻击者可以通过构 造特定的请求包来达到提升权限的目的。首先我们来说一下利用方式。
1、利用方式
实验环境:
域:YUNYING.LAB
域控:WindowsServer 2008 R2 x64(DC)
域内主机:Windows7 x64(s1):域帐户ts1
所需工具:
Pykek
mimikatz
攻击流程:
实验之前需要在域控主机查看是否安装了KB3011780补丁,可通过systeminfo来查看。
一、首先在域内主机s1上通过dir来访问域控的共享文件夹,示拒绝访问。
二、通过Pykek工具利用漏洞,我这里使用的是将python脚本编译之后的exe文件。
参数说明:
-u 域账号+@+域名称,这里是ts1+@+yunying.lab
-p 为当前用户的密码,即ts1的密码
-s为ts1的SID值,可以通过whoami/all来获取用户的SID值
-d为当前域的域控
脚本执行成功会在当前目录下生成一个 ccache 文件。
三、使用 mimikatz 导入生成的 ccache 文件,导入之前 cmd 下使用命令 klist purge 或者在 mimikatz 中使用 kerberos::purge 删除当前缓存的 kerberos 票据。
再次 dir 访问域控共享已经可以成功访问。
2、漏洞原理
MS14068工具在使用过程中抓包可以看到s1和域控192.168.254.130(实质上是与安装在域控上的KDC)有KRB_AS_REQ、KRB_AS_REP、KRB_TGS_REQ、KRB_TGS_REP四次交互。
下面根据流程和工具源码来看漏洞是如何利用的:
KRB_AS_REQ
首先程序通过build_as_req函数构建AS_REQ,在这里可以看到,参数pac_request设置为false。
也就是说设置了这个参数之后会向 KDC 申请一张不包含 PAC 的 TGT 票据,这是微软默 认的设计,在下列链接中有详细说明。 https://docs.microsoft.com/en-us/previous-versions/aa302203(v=msdn.10)#securityconsiderations
通过 PCAP 包可以更直观的看到在 AS-REQ 请求中的 include-pac:False 字段。这是造成这个漏 洞的第一个因素。
KRB_AS_REP
在AS发起请求之后,KDC(AS)将返回一张不包含有PAC的TGT票据给Client。在这里是tgt_a。
抓包可以看到这个以 268fdb 开头的 TGT 票据。
KRB_TGS_REQ
攻击脚本使用了两个关键函数来实现这个过程,首先通过build构造PAC,然后通过build_tgs_req函数构造TGS-REQ的内容。
build_pac
当Client接收到AS返回的不带有PAC的TGT之后通过脚本中的build_pac函数开始构造PAC。
这里我们重点关注一下 PAC 中的 chksum1 和 chksum2,也就是“PAC 的引入”中提到的 PAC 的两个数字签名 PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM。 注意一下其中第一个参数 server_key[0]和 kdc_key[0]的值其实是程序指定的 RSA_MD5, 而 Key 的值为 None,但原则上来说这个加密方式是应该由 KDC 来确定的。也就是说加密 PAC_SERVER_CHECKSUM 和 PAC_PRIVSVR_CHECKSUM 这两个数字签名的 Key 应该分别是
同时在这个过程中我们也需要关注一下 user_sid 这个参数,build_pac 函数会将其分割, 然后重新构造高权限的 sid 的值。在这里 user_sid 的值为 S-1-5-21-4249968736-1423802980- 663233003-1104,分割之后 domain_sid 为 S-1-5-21-4249968736-1423802980-663233003, user_id 为 1104。
其中 512、520、518、519 分别为不同的组的 sid 号。513 为 DOMAIN USERS 组。通过这种方 式构造了包含高权限组 SID 的 PAC。
build_tgs_req
在build_tgs_req函数的参数中,authorization_data对应的为build_pac生成的pac。
这里将 PAC 传入 build_tgs_req 之后使用 subkey 将其加密。
而通过下图可以看到 subkey 其实是函数 generate_subkey 生成的一串 16 位的随机数。
那现在为止出现的问题有:
A、在域中默认允许设置Include-pac的值为False(不能算漏洞,应该是微软对于某些特定场景的特殊考虑设计出的机制);
B、PAC中的数字签名可以由Client端指定,并且Key的值可以为空;
C、PAC的加密方式也可以由Client指定,并且Key的值为generate_subkey函数生成的16位随机数;
D、构造的PAC中包含高权限组的SID内容。
也就是说通过这几点Client完全伪造了一个PAC发送给KDC,并且KDC通过Client端在请求中指定的加密算法来解密伪造的PAC以及校验数字签名,并验证通过。
通过抓包可以看到在这个过程中将接收的TGT(268fdb开头)和加密方式为ARCFOUR-HMAC-MD5的PAC内容。
KRB_TGS_REP
KDC在根据对伪造的PAC验证成功之后,返回给Client端一有新的TGT,并且这个TGT会将Pykek生成的PAC包含在其中,这里正常情况下返回的其实是一张用于发送给Server端做认证的ST票据。
当 Pykek 工具接收到新的 TGT 之后就将其保存生成 ccache 文件。也就是说这时 Client 已 经获得了一张包含有高权限 PAC 内容的正常的 TGT 票据(564eab 开头)。
使用 Mimikatz 利用 TGT 访问 DC 共享文件夹 这时我们通过 mimikatz 来导入票证,并且用 dir//dc.yunying.lab/c$来访问域控的共享文件夹。
抓包可以看到这时 Client 端发起了两次 TGS-REQ 请求,重点关注一下第一次,此时用的票据 就是使用 mimikatz 导入的 TGT,也就是上面 KRB_TGS_REP 过程中返回的那个 tgt_b(564eab 开头)。
请求之后返回了一张针对 dc.yunying.lab(域控)的 CIFS 票据也就是正常流程中的 ST(Service Ticket)票据(234062 开头):
这时在抓的包中发现并没有 AP_REQ 这个流程,是因为在 Kerberos 中 AP_REQ 这个过程放在 了服务的第一次请求中,这里是放在 SMB 的 Session Setup Request 中(其他协议同理,比如 HTTP 协议是放在 GET 请求中)。
然后在 SMB 的 Session Setup Response 中做出响应,也就是 AP-REP 这个流程。
到此为止 Client 能够越权访问域控的共享文件夹。
下面我们总结一下通过上面的分析找到的微软所犯的三个错误:
第一个错误:
在KDC机构对PAC进行验证时,对于PAC尾部的签名算法,虽然原理上规定必须是带有Key的签名算法才可以,但微软在实现上,却允许任意签名算法,只要客户端指定任意签名算法,KDC服务器就会使用指定的算法进行签名验证。
第二个错误:
PAC没有被放在TGT中,而是放在了TGS_REQ数据包的其它地方。但可笑的是,KDC在实现上竟然允许这样的构造,也就是说,KDC能够正确解析出没有放在其它地方的PAC信息。
第三个错误:
只要TGS_REQ按照刚才漏洞要求设置,KDC服务器会做出令人吃惊的事情:它不仅会从Authenticator中取出来subkey把PAC信息解密并利用客户端设定的签名算法验证签名,同时将另外的TGT进行解密得到SessionKeya-kdc;
在验证成功后,把解密的PAC信息的尾部,重新采用自身Server_key和KDC_key生成一个带Key的签名,把SessionKeya-kdc用subkey加密,从而组合成了一个新的TGT返回给Client-A
整个大概流程就是 先请求一个不包含PAC的TGT 然后用域用户的sid来伪造高权限的sid构成PAC 然后通过tgs_req传给KDC req_rep返回一个新的TGT 而不是ST 也正是这个高权限的TGT起到最后的作用
参考:https://www.freebuf.com/articles/system/197160.html
https://blog.csdn.net/zy_strive_2012/article/details/51698780
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!