references:
约定:
- DS服务器:Delegation Server——委派服务器
- OB用户:on behalf user——被委派的用户
- RS服务器:Resource Server——资源服务器
0x1 简介
在之前的文章中,我们介绍了Kerberos非约束委派及利用方式,那么在这篇文章中,我将会介绍Windows AD环境中Kerberos协议的约束委派
约束委派中的约束二字具体体现在下图中:
也就是说,我们可以限制DS服务器所能够访问到的服务
比如上图中,DS服务器ds-server只能够访问到RS服务器WIN-JTPO01EANAQ
的time服务
你或许注意到了,上图中有两个选项,一个仅可以使用Kerberos,另一个可以使用任何身份验证协议
这两个选项分别对应微软为Kerberos协议开发的两个拓展:
- S4U2proxy
- S4U2self
其中第二个拓展提供了一个叫做Protocol Transition
(协议转换)的特性
也就是说,不管客户端使用何种认证协议认证到DS服务器,都能够使用该用户的身份通过DS服务器来访问RS服务器
大致过程如下:
- OB用户使用NTLM(或者其他的身份认证协议)认证到DS服务器
- DS服务器代表OB用户向KDC请求一个针对自身的TGS票据(OB@[email protected]),这个过程叫做S4U2self
- DS服务器使用上一步获取的TGS票据向KDC请求一个针对RS服务器的TGS票据(OB@time/[email protected]),这个过程叫做S4U2proxy,time是我们在上图中指定的服务类型
下面我们就进行抓包分析,以便更好地理解这两个扩展
0x2 抓包
我们在配置好ds-server
服务器的委派设置之后,使用impacket中的examples脚本中的getST.py来进行演示
执行如下命令执行完整的S4U请求(先执行S4U2self请求,然后执行S4U2proxy请求)
python3 getST.py mother.fucker/ds-server$ -hashes :061c54f1f5311e1f47958465e16bab65 -impersonate Administrator -spn time/WIN-JTPO01EANAQ.mother.fucker -dc-ip 192.168.64.128
wireshark过滤条件直接写tcp.port==88
即可
0x2.1 S4U2self
0x2.1.1 DS服务器获取TGT票据
在实际的S4U过程中,这一步是在DS服务器开机之后就完成的,但是由于我们是使用工具模拟请求,所以需要先获取到DS服务器的TGT票据
这也是为什么我们在上面的命令中需要使用ds-server$
账户的hash
该过程在Kerberos协议分析一文中已经讲解过,在此不再赘述
0x2.1.2 DS服务器代表OB用户获取针对自己的TGS票据
TGS-REQ:
小标题中的针对自己的TGS票据意思就是在请求的票据中不包含服务类型,而只有DS服务器的机器账户名称
可以看到,在该TGS请求中,提交的是DS服务器自己的TGT票据,我们可以使用解密工具解密authenticator字段来证明
另外一个重要的字段就是PA-DATA
,类型为pA-FOR-USER
下面是微软[MS-SFU]文档中对PA-FOR-USER
的描述
上图中最后给出了该字段的结构,其中cksum
为userName
、userRealm
和auth-package
的校验和
校验和的计算需要TGT session key,userName就是OB用户
因此我们完全有能力自行构造PA-FOR-USER
字段
你会发现,我们居然不需要OB用户的任何凭据信息就可以对其进行委派,只需要知道OB用户所在的域名和其samAccountName
即可
TGS-REP:
可以看到,该票据的所有者是Administrator
,也就是OB用户,我们可以通过解密ticket.enc-part
来进一步确认
0x2.2 S4U2proxy
0x2.2.1 DS服务器代表OB用户获取针对RS服务器的TGS票据
TGS-REQ:
从上图中可以看到DS服务器拿着自己的TGT票据,以及在req-body中的additional-tickets
向KDC申请time/WIN-JTPO01EANAQ.mother.fucker
票据
additional-tickets
就是在S4U2self阶段获取到的针对DS服务器自身的TGS票据
TGS-REP:
该票据就是颁发给Administrator用户的,我们可以通过解密ticket.enc-part
来进一步确认该票据的所有者
至此,整个约束委派过程就完成,我们获取到了用于访问RS服务器WIN-JTPO01EANAQ.mother.fucker
的time服务的票据
0x3 拓展
0x3.1 TGS票据中SPN服务类型可以任意修改
票据通过TGS-REP从KDC返回给客户端,也就是其中的ticket
字段,该字段中有一个enc-part
,是使用目标服务的账户哈希进行加密的,我们可以看一下该字段解密后的结构:
其中没有任何一个字段与SPN有关,也就是说,即便我们修改了SPN的服务类型,也不会导致票据失效
而且事实的确如此,就算将我们上面获取到的票据中SPN的服务类型由time
改为cifs
,也依然可以正常使用
可以使用这个修改过的getST.py在获取TGS票据的同时对服务类型进行修改,只需要将执行的命令改成下面即可:
python3 getST.py mother.fucker/ds-server$ -impersonate Administrator -spn time/WIN-JTPO01EANAQ.mother.fucker -altservice cifs -dc-ip 192.168.64.128 -aesKey 63b97c1cc1e372a0622452fad91adfb50ac06961e470a1ea1d508ac607f42239
使用获取到的cifs票据访问目标服务器文件系统
注意:只有运行在同一个服务账户下的服务才可以互相更改,比如time服务运行在example_service_user账户下,那么就算你改成了cifs服务,也你无法访问服务器的文件系统,因为cifs服务并不是由example_service_user账户运行的,一般由计算机账户运行
0x3.2 user account control
回到文中的第一张图
如果我们选择了使用任何身份验证协议
,那么我们的DS服务器账户的useraccountcontrol
属性的值为0x1001000
对照[MS-ADTS]中对userAccountControl Bits的描述:
0000 0001 0000 0000 0001 0000 0000 0000
第7位和第19位两个比特位启用,两者分别对应TA
和WT
TA代表ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION
,启用了该bit位的账户可以代表其他用户通过S4U2self请求获取到一个针对自己的TGS票据,且该票据拥有forwardable标志位(可转发),如果票据不可转发,那么S4U2proxy请求将会失败
WT标志位表示该账户是机器账户
我们可以尝试将ds-server
账户userAccountControl
属性的TA标志位取消掉(将其值设置为4096),然后再执行S4U2self,查看返回的票据是否具有forwardable
标志位
python3 getST.py mother.fucker/ds-server$ -impersonate Administrator -self -dc-ip 192.168.64.128 -aesKey 63b97c1cc1e372a0622452fad91adfb50ac06961e470a1ea1d508ac607f42239
使用describeTicket.py脚本查看票据的详细信息
python3 describeTicket.py -u ds-server$ -d mother.fucker --aes 63b97c1cc1e372a0622452fad91adfb50ac06961e470a1ea1d508ac607f42239 C:\Users\x\Downloads\tmp\Administrator@ds-server$@MOTHER.FUCKER.ccache
可以看到S4U2self请求返回的票据并不带有forwardable
标志位
那么下一步的S4U2proxy请求就回应为additional-ticket中的票据无法被转发而失败:
另外,我们可以看到ds-server
的委派配置变成了下面这样:
这是因为我们前面更改userAccountControl属性,取消了TA标志位
也就是说没有TA标志位的委派服务器执行S4U2self请求是没有意义的(在某些特殊的攻击场景下会有用),因为返回的票据并不能用于S4U2proxy
该选项相较于上面的使用任何身份验证协议
更加安全,因为我们需要先使用OB用户的凭据来获取一个针对DS服务器的票据,然后才可以执行S4U2proxy来获取针对RS服务器的票据,这样就大大增加了攻击难度
0x4 利用
可以使用csvde搜索域内所有msDS-AllowedToDelegateTo
属性不为空的账户:
csvde -s 192.168.64.128 -b Administrator mother.fucker qwe123... -d "dc=mother,dc=fucker" -r (msds-AllowedToDelegateTo=*/*) -l dn,sAMAccountName,msds-AllowedToDelegateTo,userAccountControl -m -f res.csv -u
然后我们需要通过userAccountControl
的值确认是否启用了TA
标志位,执行下面的Python代码即可:
print(True if (uac值 & (1<<24)) == (1<<24) else False)
由于TA为第7位(从0开始),因此可以通过和左移24位的1进行与运算来判断该bit位是否启用
如果TA比特位启用,且可以委派到指定服务器,那么一旦我们获得了该委派服务账户的凭据,我们就可以冒充任意账户去获取指定服务器的票据
python3 getST.py mother.fucker/ds-server$ -hashes :061c54f1f5311e1f47958465e16bab65 -impersonate Administrator -spn time/WIN-JTPO01EANAQ.mother.fucker -altservice cifs -dc-ip 192.168.64.128
因此,这个利用难度还是比较高的,后面我们将会介绍Kerberos基于资源的约束委派,在这种类型的约束委派中,S4U2self和S4U2proxy将会起到非常重要的作用
0x5 结语
没什么新的内容,都是网上能找得到的东西,这里不过是炒炒冷饭而已,权当笔记
如有不足之处,欢迎师傅们指点