前言:作为非约束/约束委派的学习笔记,自己尽量讲其讲的详细
参考文章:https://daiker.gitbook.io/windows-protocol/kerberos/2
参考文章:https://en.hackndo.com/constrained-unconstrained-delegation/
域委派是指:将域内用户的权限委派给服务账号,使得服务账号能以用户权限开展域内活动
懂一个东西的产生,肯定要先知道为什么会产生这个东西?
在Windows 2000 Server首次发布Active Directory时,Microsoft必须提供一种简单的机制来支持用户通过kerberos向web server进行身份验证并需要代表该用户更新后端数据库服务器上的记录的方案。这通常称为"kerberos双跳问题",并且要求进行委派,以便web server在修改数据库记录时模拟用户。
这里说的"以便web server在修改数据库记录时模拟用户" 需要如何理解?
我自己理解的是就比如数据库中的相关数据需要修改,如果此时如果是让当前的web server的服务账户去进行修改的话,那么也就无法记录到到底是谁去修改了这个数据,此时如果出了问题就不知道该去问谁了,这种业务情况下就可能就是需要委派这种功能来进行解决,那么委派之后的情况就是,让当前的web server的服务账户去操作,但是web server同样带有客户的信息,在修改相关数据的时候,用的是对应客户操作者的记录。
这里还需要注意的一点就是接受委派的用户只能是服务账户或者主机账户
在域内只有主机账号和服务账号才有委派属性主机账号:
1、机器账户:活动目录中的computers组内的计算机,也被称为机器账号。
2、服务账号:域内用户的一种类型,是服务器运行服务时所用的账号,将服务运行起来加入域内,比如:SQLServer,MYSQL等,还有就是域用户通过注册SPN也能成为服务账号。
服务账号(Service Account),域内用户的一种类型,服务器运行服务时所用的账号,将服务运行起来并加入域。就比如 SQL Server在安装时,会在域内自动注册服务账号SqlServiceAccount,这类账号不能用于交互式登录。
目前域委派存在三种类型,非约束委派、约束委派、基于资源的约束委派,这里先来讲非约束委派和约束委派。
客户想要访问一个指定服务的时候,如果该服务是被指定为需要非约束委派的话,那么该客户在申请完TGT,然后再申请完TGS(此时TGS会包含TGT),最后再拿着这个TGS向指定的服务(非约束委派),此时这个服务(非约束委派)可以获取客户在TGS中保存的TGT,又因为服务被设置为非约束委派,所以该服务会将TGS中保存的TGT进行保存在本地内存中,用于下次方便操作,最后再用这个TGT模拟用户访问 实现这个服务中可能需要的其他服务(我这里说的其他服务指的是可能也需要客户的票据)的,比如我下面举的一个实际需求。
微软的非约束委派的请求流程图如下所示
用户通过发送KRB_AS_REQ消息请求TGT1
KDC在KRB_AS_REP消息中返回TGT1
用户再通过TGT1向KDC请求转发TGT2(这里的TGT2跟TGT1不同,这里的TGT2票据属性中存在可转发的标记Forwarded)
在KRB_TGS_REP消息中返回转发TGT2(可转发的标记Forwarded)
用户使用TGT1向KDC申请访问Service1的ST(服务票据)
TGS返回给用户一个ST(服务票据)
到第六步这里,其实大家都看到了就是一个完整的kerberos票据验证流程,唯一有一个不同,那就是在请求了TGT1票据之后还会再去请求另一张TGT2票据,这个TGT2的票据跟TGT1唯一的不同点就是带有"可转发的标记Forwarded"
用户发送KRB_AP_REQ请求至Service1,这个请求中包含了TGT1和ST(服务票据)、TGT2、TGT2的Session key
在第七步的时候可以看到,发送给Service1的时候会发送了相关的TGT1 ST 和 TGT2 TGT2的Session key,需要注意的就是这里的TGT2(可转发的标记) TGT2的Session key会被存储到Service1中用于之后的请求
Service1使用用户的TGT2(可转发的标记)通过KRB_TGS_REQ发送给KDC,以用户的名义请求能够访问Service2的票据ST2
KDC在KRB_TGS_REP消息中返回Service2到Service1的票据ST2
Service1以客户的名义用ST2发送KRB_AP_REQ请求
为什么是以客户的名义呢?个人理解就是因为上面我们说的TGT2(可转发的标记)来请求Service2。
Service2响应步骤10中Service1的请求
Service1响应步骤7中用户的请求
在这个过程中的TGT转发机制,没有限制Service1对TGT2的使用,也就是说Service1可以通过TGT2来请求任意服务
KDC返回步骤13中请求的票据,15和16即为Service1通过模拟用户来访问其他ServiceXXXX
当user访问service1时,如果service1的服务账号如果开启了Unconstrained Delegation(非约束委派),则当user访问service1时会将user的TGT(带有可转发标记)发送给service1并保存在内存中以备下次重用,然后service1 就可以利用这张TGT以user的身份去访问域内的任何服务(任何服务是指user能访问的服务)了。
我这里会把自己的疑惑点都给理一遍作为记录
问题1、网上的文章"在域内只有主机账号和服务账号才有委派属性主机账号",所以我这里会用来一遍 "只有主机账户" 和 "只有服务账户" 的环境
原生的一台 WIN-BING-PC 机器名称的机器,什么委派我都还没做
同样其相关自定义SPN服务也不存在,默认如下图所示,这里需要注意的一点,你会看到这个WSMAN/WIN-BING-PC
,后面在通过WINRM连接验证kerberos的时候的时候需要用到这个SPN服务,否则无法进行连接。
先来测试下环境的正确性,就是先试下委派是否存在,此时我什么都还没做,应该是不存在相关的委派利用的
然后域控进行访问 WIN-BING-PC 这台机器,通过命令Enter-PSSession -ComputerName WIN-BING-PC
,走是的WSMAN服务
然后导出 WIN-BING-PC 机器中的票据,可以发现只有自己相关的凭据。
mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit
非约束委派的设置,这里设置了主机账户为非约束委派
通过adFind进行查询,也可以看到此时已经被设置为了非约束委派
adFind -b dc=hengge,dc=com -f "(&(objectCategory=computer)(objectClass=computer)(userAccountControl:1.2.840.113556.1.4.803:=524288))" -dn
然后域控再次访问 WIN-BING-PC 这台机器,通过命令dir \\WIN-BING-PC\c$
,走是的kerberos的cifs协议
然后导出 WIN-BING-PC 机器中的票据
mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit
结果发现还是没有相关的administrator的票据kirbi
接着我用域控通过命令来访问Enter-PSSession -ComputerName WIN-BING-PC
然后导出 WIN-BING-PC 机器中的票据
mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit
然后会看到一张基于导出了相关的域控中administrator的高权限票据
访问域控 dc1.hengge.com ,可以看到当前没有权限访问
然后这里来进行导入票据访问,可以发现成功进行访问了
mimikatz "kerberos::ptt [0;7f4a8][email protected]" exit
总结:我想了下为什么dir的时候不行,这个点我还是不太懂,按道理SPN中是可以进行CIFS协议访问的,并且通过机器名走的应该是kerberos,但是最终却无法进行导出,这个点不太懂,因为域控相关的补丁没有打,所以抓包也抓不了,之后这个点知道了,自己再来补上吧!
在域中服务账户也可以进行相关非委派约束,我这里先创建一个域用户账号,然后之后将这个域用户作为服务账户
然后将这个账户sqladmin指定到一个对应的SPN服务,被设置了SPN服务之后,当前域账户同时也成为了服务账户
setspn -U -A variant/golden sqladmin
接着为这个sqladmin域用户配置非约束委派
之后将 sqladmin 用户登录到 WIN-BING-PC 上面,然后跟上面一样,让域控模拟访问被设置了非约束委派的机器,如下图所示
Enter-PSSession -ComputerName WIN-BING-PC
接着在 WIN-BING-PC 中导出相关票据,你会发现并没有相关高权限票据导出
mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit
最终作为服务账户这里是没有利用成功的,我这里自己想了下,出现的问题应该是我用sqladmin登录了一台计算器,而本身sqladmin是服务用户并且被设置了非约束委派。自己认为其实是可以利用的,不过sqladmin应该需要作为第三方软件(比如mssql,mysql等)的服务账户来进行启动,然后让高权限,比如域管账户去访问mssql,mysql等服务才可以。但是因为没有相关的环境,自己比较懒,也就不去尝试了...
参考文章:https://adsecurity.org/?p=4056
原理实现:Windows Print System Remote Protocol是MS-RPRN中的一个老旧,但是默认的方法,通过该协议可以让域用户使用MS-RPRN RpcRemoteFindFirstPrinterChangeNotification (Ex)方法强制运行Spooler服务的机器通过kerberos或者NTLM验证攻击者的目标。
可以看到默认的2012和2008的机器上都会开启Spooler相关的服务
不过自己这里也测试失败了,运行了就报错,不知道是不是编译的问题还是什么...
这里用petitpotam来进行替代printbug
python petitpotam.py -u '' -p '' -d '' 192.168.4.11 192.168.4.130
接下来开始重头戏,到底什么是S4U2proxy和S4U2self
S4U2self和S4U2proxy出现的原因就是由于非约束委派的不安全性。
其中引入了包括一组名为S4U2Self(Service for User to Self)和S4U2Proxy(Service forUser to Proxy)的Kerberos协议扩展,这两个子协议是TGS协议的扩展
由于非约束委派的不安全性,微软在windows2003中发布了约束委派的功能,如下所示
在约束委派中的kerberos中,用户同样还是会将TGT发送给相关受委派的服务,但是由于S4U2proxy的影响,对发送给受委派的服务去访问其他服务做了限制,不允许受委派的服务代表用户使用这个TGT去访问任意服务,而是只能访问指定的服务。
允许受约束委派的服务代表任意用户向KDC请求服务自身,从而获得一张该用户(任意用户)的对当前受约束委派服务的票据TGS(ST),该服务票据TGS(ST)包含了用户的相关信息,比如该用户的组信息等。
允许受约束委派的服务通过服务票据ST,然后代表用户去请求指定的服务。
用户请求一个约束委派的服务流程图如下:
请求过程如下:
用户向Service1发送请求。
这时在官方文档中的介绍是在这一流程开始之前用户已经通过了相关的kerberos验证,此时的Service1中已经存在了用户的TGT1票据(Forwardable标记),然后通过S4U2self模拟用户向KDC请求自身服务的ST1票据(Forwardable标记)
KDC这时返回给Service1一个用于Service1自身的ST1票据(Forwardable标记),并且Service1用这个ST1票据(Forwardable标记)完成和用户的验证过程。
Service1在步骤3使用模拟用户申请的ST1票据(Forwardable标记)完成与用户的验证,然后ST1票据(Forwardable标记)响应用户。
前四步的总结:
Service1是获得了用户的TGT(Forwardable的标记)
Service1通过模拟用户向KDC请求自身服务的ST1票据(Forwardable标记)
用户再次向Service1发起请求,此时Service1需要以用户的身份访问Service2。
这里官方文档提到了两个点:
Service1已经验证通过,并且有一个有效的TGT(Forwardable标记)。
Service1有从用户到Service1的Forwardable ST1(Forwardable标记)。
Service1通过S4U2proxy代表用户用ST1(Forwardable标记,在S4U2SELF阶段获得的TGS票据,会放在AddtionTicket字段中)向KDC请求一个用于认证Service2的ST(我们称为ST2)。用户在ST1中通过cname(client name)和crealm(client realm)字段标识。
KDC在接收到步骤6中Service1的请求之后,进行验证,然后返回Service2的服务票据ST2(Forwardable标记)
Service1代表用户使用ST2请求Service2。
Service2响应Service1的请求。
Service1响应用户的请求。
在这个过程中:
S4U2self可以代表用户去请求针对其自身的kerberos服务票据(ST),这里s4u2self的作用其实就是为了解决用户不能以kerberos方式进行验证的一种方法,因为用户自己不能通过kerberos去获取相关的ST票据,所以可以通过s4u2self的方法去获取一张ST票据来用于之后的kerberos的协议认证
S4U2proxy可以以用户的名义请求其它服务的ST
"同时注意票据的Forwardable标记,有Forwardable标记为可转发的是能够通过S4U2Proxy扩展协议进行转发的,如果没有标记则不能进行转发" 这个说法不正确,这个可以参考daiker的文章中的内容,如下图所示
在Windows系统中,普通用户的属性中没有委派(Delegation)这个选项卡,只有服务账号、主机账号才有,也就是当前用户账户下存在相对应的服务,比如mssql,http等等服务
在域中只有服务账户才能有委派功能,所以先把用户yuyonghu01设置为服务账号。
setspn -U -A https/golden yuyonghu01
setspn -l xxxxx
首先:将用户yuyonghu01设置为 信任此用户作为其他任何服务的委派
查询非约束委派主要是通过搜索userAccountControl属性包含ADS_UF_TRUSTED_FOR_DELEGATION
的主机或账户
非约束委派的查询:
通过Import-Module PowerView.ps1加载PowerView脚本之后使用下面的命令进行查询。
查询域中配置非约束委派的账户:Get-NetUser -Unconstrained -Domain rootkit.org
查询域中配置非约束委派的主机:Get-NetComputer -Unconstrained -Domain rootkit.org
查询约束委派则通过搜索userAccountControl属性包含TRUSTED_TO_AUTH_FOR_DELEGATION
的主机或用户
约束委派的查询:
查询域中配置约束委派的账户:Get-DomainUser -TrustedToAuth -Domain rootkit.org
查询域中配置约束委派的主机:Get-DomainComputer -TrustedToAuth -Domain rootkit.org
在内网中利用约束委派进行攻击的最重要的一点是:约束委派的服务代表用户获得针对服务自身的kerberos票据这个过程,服务是不需要用户的凭据的,通过这个点,只要我们有约束委派的服务的账户和密码,那么通过这个服务就可以直接来进行攻击可以访问的相关服务。
约束委派的设置:
1、首先调用powerview模块进行约束委派的查询
get-DomainUser -TrustedToAuth -Domain pentest.God
2、利用kekeo向KDC请求TGS服务票据
申请TGT:
tgt::ask /user:yuyonghu01 /domain:pentest.god /password:[email protected]#QWE /ticket:yuyonghu01.kirbi伪造任意权限S4U请求,申请TGS服务票据:
Tgs::s4u /tgt:[email protected][email protected] /user:[email protected] /service:cifs/WIN-CKT0M35R6UO.pentest.god
3、导入TGS服务票据,访问对应的服务
mimikatz "kerberos::ptt [email protected]@[email protected]" exit
关于约束委派的防御方法:
1、高权限用户没有在特殊要求之下设置为不可委派,比如administrator
攻击路线:
1、判断已有的账号是否是约束/非约束委派账户
2、获取非约束委派账户凭证/主机权限
3、利用 Kerberoasting 攻击获取服务账号密码
点击下方小卡片或扫描下方二维码观看更多技术文章
师傅们点赞、转发、在看就是最大的支持