MS14068

MS14068 是一个能够使普通用户提权到域控权限的权限提升漏洞。攻击者可以通过构 造特定的请求包来达到提升权限的目的。首先我们来说一下利用方式。

1、利用方式

实验环境:

域:YUNYING.LAB

域控:WindowsServer 2008 R2 x64(DC)

域内主机:Windows7 x64(s1):域帐户ts1

所需工具:

Pykek

mimikatz

攻击流程:

实验之前需要在域控主机查看是否安装了KB3011780补丁,可通过systeminfo来查看。

一、首先在域内主机s1上通过dir来访问域控的共享文件夹,示拒绝访问。

image-20220214223157361

二、通过Pykek工具利用漏洞,我这里使用的是将python脚本编译之后的exe文件。

参数说明:

-u 域账号+@+域名称,这里是ts1+@+yunying.lab

-p 为当前用户的密码,即ts1的密码

-s为ts1的SID值,可以通过whoami/all来获取用户的SID值

-d为当前域的域控

image-20220214223234344

脚本执行成功会在当前目录下生成一个 ccache 文件。

image-20220214223245875

三、使用 mimikatz 导入生成的 ccache 文件,导入之前 cmd 下使用命令 klist purge 或者在 mimikatz 中使用 kerberos::purge 删除当前缓存的 kerberos 票据。

image-20220214223257254

再次 dir 访问域控共享已经可以成功访问。

image-20220214223310314

2、漏洞原理

MS14068工具在使用过程中抓包可以看到s1和域控192.168.254.130(实质上是与安装在域控上的KDC)有KRB_AS_REQ、KRB_AS_REP、KRB_TGS_REQ、KRB_TGS_REP四次交互。

image-20220214223340645

下面根据流程和工具源码来看漏洞是如何利用的:

KRB_AS_REQ

首先程序通过build_as_req函数构建AS_REQ,在这里可以看到,参数pac_request设置为false。

image-20220214223410656

也就是说设置了这个参数之后会向 KDC 申请一张不包含 PAC 的 TGT 票据,这是微软默 认的设计,在下列链接中有详细说明。 https://docs.microsoft.com/en-us/previous-versions/aa302203(v=msdn.10)#securityconsiderations

image-20220214223437888

通过 PCAP 包可以更直观的看到在 AS-REQ 请求中的 include-pac:False 字段。这是造成这个漏 洞的第一个因素。

image-20220214223450215

KRB_AS_REP

在AS发起请求之后,KDC(AS)将返回一张不包含有PAC的TGT票据给Client。在这里是tgt_a。

image-20220214223507725

抓包可以看到这个以 268fdb 开头的 TGT 票据。

image-20220214223521417

KRB_TGS_REQ

攻击脚本使用了两个关键函数来实现这个过程,首先通过build构造PAC,然后通过build_tgs_req函数构造TGS-REQ的内容。

image-20220214223650466

build_pac

当Client接收到AS返回的不带有PAC的TGT之后通过脚本中的build_pac函数开始构造PAC。

image-20220214223711517

这里我们重点关注一下 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 应该分别是

image-20220214223729644

同时在这个过程中我们也需要关注一下 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。

image-20220214223742596

其中 512、520、518、519 分别为不同的组的 sid 号。513 为 DOMAIN USERS 组。通过这种方 式构造了包含高权限组 SID 的 PAC。

image-20220214223753866

build_tgs_req

在build_tgs_req函数的参数中,authorization_data对应的为build_pac生成的pac。

image-20220214223809904

这里将 PAC 传入 build_tgs_req 之后使用 subkey 将其加密。

image-20220214223820776

而通过下图可以看到 subkey 其实是函数 generate_subkey 生成的一串 16 位的随机数。

image-20220214223831544

image-20220214223836823

那现在为止出现的问题有:

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内容。

image-20220214223905906

KRB_TGS_REP

KDC在根据对伪造的PAC验证成功之后,返回给Client端一有新的TGT,并且这个TGT会将Pykek生成的PAC包含在其中,这里正常情况下返回的其实是一张用于发送给Server端做认证的ST票据。

image-20220214223924213

当 Pykek 工具接收到新的 TGT 之后就将其保存生成 ccache 文件。也就是说这时 Client 已 经获得了一张包含有高权限 PAC 内容的正常的 TGT 票据(564eab 开头)。

image-20220214223935716

使用 Mimikatz 利用 TGT 访问 DC 共享文件夹 这时我们通过 mimikatz 来导入票证,并且用 dir//dc.yunying.lab/c$来访问域控的共享文件夹。

image-20220214223946266

抓包可以看到这时 Client 端发起了两次 TGS-REQ 请求,重点关注一下第一次,此时用的票据 就是使用 mimikatz 导入的 TGT,也就是上面 KRB_TGS_REP 过程中返回的那个 tgt_b(564eab 开头)。

image-20220214223959527

请求之后返回了一张针对 dc.yunying.lab(域控)的 CIFS 票据也就是正常流程中的 ST(Service Ticket)票据(234062 开头):

image-20220214224016078

这时在抓的包中发现并没有 AP_REQ 这个流程,是因为在 Kerberos 中 AP_REQ 这个过程放在 了服务的第一次请求中,这里是放在 SMB 的 Session Setup Request 中(其他协议同理,比如 HTTP 协议是放在 GET 请求中)。

image-20220214224130620

然后在 SMB 的 Session Setup Response 中做出响应,也就是 AP-REP 这个流程。

image-20220214224142525

到此为止 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 协议 ,转载请注明出处!