信息收集

端口扫描

使用nmap进行端口探测,发现存在88、135等多个端口。

1673341863_63bd2ba739ed137972616.png!small?1673341864311

通过nmap发现,这是一个运行 Active Directory (AD) 域控制器 (DC) 的 Windows 服务器。

1673341877_63bd2bb5504e47651cc3d.png!small?1673341877970

首先,我们现在知道 DC 域名“support.htb”。我们可以枚举 DNS 服务器来确认系统的名称。

1673341889_63bd2bc17546098953f26.png!small?1673341889917

我们的 dig 命令确认服务器的计算机名称是“dc”,域名是“support.htb”。

1673341902_63bd2bcee8e7d13deeb6f.png!small?1673341903504

SMB 文件共享枚举

SMB 文件共享是重要的信息收集方式,然后我们去枚举SMB 文件共享。

1673341918_63bd2bde904535a745b6b.png!small?1673341919018

发现了一个名为“support-tools”的共享。

1673341945_63bd2bf94e387b980632a.png!small?1673341946522

使用“dir”命令,我们可以获得存储在“support-tools”上的文件的目录列表。然后下载所有文件,去在本地进行分析。

在连接的 SMB 会话中,运行以下命令。

SMB:> mask ""
SMB:> recurse ON
SMB:> prompt OFF
SMB:> mget *

1673341961_63bd2c09159be4518f259.png!small?1673341962075

“UserInfo.exe.zip”。检查文件的哈希值,发现这个“UserInfo.exe.zip”文件包含一个“UserInfo.exe”。

1673341975_63bd2c17b213aa30b7fd2.png!small?1673341976224

枚举策略

当面对具有如此多端口的 Windows 服务器时,我通常会根据我的舒适程度优先处理它们。我将生成一个分层列表,其中包含一些关于我可能在每个列表中寻找的内容的粗略想法:

  • 必须看
    • SMB - 寻找任何开放的共享,看看我能在那里找到什么。
    • LDAP - 我可以在没有凭据的情况下获取任何信息吗?
  • 如果那些失败
    • Kerberos - 我可以暴力破解用户名吗?如果我找到任何东西,它们可以作为 REP 烤吗?
    • DNS - 我可以进行区域传输吗?暴力破解任何子域?
    • RPC - 是否可以匿名访问?
  • 学分注意事项
    • WinRM - 如果我能在 Remote Management Users 组中找到用户的凭据,我可以获得一个 shell

分析 UserInfo.exe

我们可以使用“mono”或“wine64”等模拟器运行 Windows 可执行文件。

1673341992_63bd2c28ad0e9195c17a4.png!small?1673341993308

LDAP-TCP 389

使用ldapsearch获取文件内容。

1673342011_63bd2c3bb8ce88ee2f718.png!small?1673342012237

要继续搜索,它说我需要身份验证(“成功绑定”):

1673342025_63bd2c494b88b1e7267cf.png!small?1673342025771

创建一个目录,然后解压压缩包。

1673342045_63bd2c5d92c20a1da8628.png!small?1673342047595

1673342053_63bd2c65dce81537bdd6c.png!small?1673342054489

然后给Userinfo.exe增加执行权限。

1673342069_63bd2c75a350b70843354.png!small?1673342070328

使用Userinfo.exe去枚举信息

1673342081_63bd2c811e0f099855f94.png!small?1673342081652

1673342091_63bd2c8b70dc3c74218ff.png!small?1673342091823

Wireshark分析网络

前面提到服务器,打开 Wireshark 并再次运行它。发现它正在寻找support.htb:

1673342108_63bd2c9c56e827aa933a9.png!small?1673342109029

接着看请求包。

1673342121_63bd2ca930752dabf1872.png!small?1673342121904

1673342136_63bd2cb8163590be3989e.png!small?1673342136544

使用 LDAP 查询:

PS > .\UserInfo.exe -v find -first john
[*] LDAP query to use: (givenName=john)
[-] No users identified with that query.

做一些基本的 LDAP 注入,让所有用户都有名字:

PS > .\UserInfo.exe find -first '*'
raven.clifton
anderson.damian
monroe.david
cromwell.gerard
west.laura
levine.leopoldo
langley.lucy
daughtler.mabel
bardot.mary
stoll.rachelle
thomas.raphael
smith.rosario
wilson.shelby
hernandez.stanley
ford.victoria

使用有效名称,它会打印出可能需要的有关用户的信息:

PS > .\UserInfo.exe user -username smith.rosario
First Name:           rosario
Last Name:            smith
Contact:              smith.rosario@support.htb
Last Password Change: 5/28/2022 7:12:19 AM

.net代码审计

恢复 LDAP 密码

静态的

我可以进一步研究 LDAP 注入,但考虑到它正在对 Support 进行 LDAP 查询,并且我已经表明这些查询需要身份验证,我将查看二进制文件以找到凭据。

将UserInfo.exe在 DNSpy 中打开。

1673342158_63bd2cce3c217f542f1fd.png!small?1673342159057
LdapQuery似乎是一个很好的起点。有两个函数printUser和query,它们可能与这两个命令匹配。

1673342175_63bd2cdf913d94440d892.png!small?1673342176009
显示它正在加载密码,然后使用用户 SUPPORT\ldap 和该密码连接到 LDAP。

我需要查看Protected.getPassword()函数(实际上是整个类):

using System;
using System.Text;

namespace UserInfo.Services
{
	// Token: 0x02000006 RID: 6
	internal class Protected
	{
		// Token: 0x0600000F RID: 15 RVA: 0x00002118 File Offset: 0x00000318
		public static string getPassword()
		{
			byte[] array = Convert.FromBase64String(Protected.enc_password);
			byte[] array2 = array;
			for (int i = 0; i < array.Length; i++)
			{
				array2[i] = (array[i] ^ Protected.key[i % Protected.key.Length] ^ 223);
			}
			return Encoding.Default.GetString(array2);
		}

		// Token: 0x04000005 RID: 5
		private static string enc_password = "0Nv32PTwgYjzg9/8j5TbmvPd3e7WhtWWyuPsyO76/Y+U193E";

		// Token: 0x04000006 RID: 6
		private static byte[] key = Encoding.ASCII.GetBytes("armando");
	}
}

我们接着往下看,没有发现别的有用的代码。

1673342197_63bd2cf5097a0a8745e1d.png!small?1673342197752

使用python解密密码

我将使用 Python 终端解密密码:

1673342211_63bd2d035b4c65ea0292f.png!small?1673342211800

动态的

在我的 Linux 系统上,我已经安装了 .NET 框架,它与mono二进制文件一起提供,也可以用来运行这个二进制文件。如果我打开 Wireshark 并运行二进制文件,我将在 LDAP 流中捕获身份验证:

1673342222_63bd2d0ec966a5d3eb850.png!small?1673342223256

使用Wireshark 在“bindRequest”的数据包中看到:

1673342235_63bd2d1be3093feb06301.png!small?1673342236970

验证信用

crackmapexec是快速展示这些信息的好方法:

1673342253_63bd2d2d62052491d521a.png!small?1673342254085

Bloodhound收集域信息

使用Bloodhound收集信息。

1673342268_63bd2d3cdb9d1fb17984c.png!small?1673342269567

下面这些就是使用Bloodhound.py收集的一些信息。

1673342284_63bd2d4cc5a301b4efb28.png!small?1673342285239

都是json格式的文件。

1673342300_63bd2d5cc22858d7a1636.png!small?1673342301805

LDAP

ldapsearch将显示 AD 中的所有项目。

1673342316_63bd2d6cbf459c43eda21.png!small?1673342317240

发现有一个名为 support 的用户。

1673342337_63bd2d81f18ecfe20c438.png!small?1673342338477

“Ironside47pleasure40Watchful”是它的密码。

1673342351_63bd2d8fd1dd9ef49ac4c.png!small?1673342352408

使用ldapdomaindump发现也存在相同的信息。

1673342367_63bd2d9f8ba7ad8ff0c7d.png!small?1673342368457

查看 Bloodhound 数据,支持显示为 Remote Management Users 的成员:

1673342381_63bd2dad4da9d7a220a88.png!small?1673342381784

获取user.txt

使用WinRM连接

evil-winrm -i 10.10.11.174 -u support -p Ironside47pleasure40Watchful

使用之前获取到的用户名和密码进行连接,连接之后获取到第一个webshell。

然后进入Desktop,获取到user.txt.

1673342403_63bd2dc32901053e2e413.png!small?1673342403570

我们接着往下看。


枚举

再次查看 Bloodhound 数据,支持用户是 Shared Support Accounts 组的成员,该组GenericAll在计算机对象上具有 DC.SUPPORT.HTB:

1673342420_63bd2dd43dc97890f8669.png!small?1673342420705

基于资源的约束委派基础

这类似于基本的约束委派,但不是授予对象权限以针对服务模拟任何用户。Resource-based Constrain Delegation在能够模拟任何用户的对象中设置。

在这种情况下,受限对象将具有一个名为msDS-AllowedToActOnBehalfOfOtherIdentity的属性,其中包含可以模拟任何其他用户的用户名。

此约束委派与其他委派的另一个重要区别是,任何对计算机帐户(GenericAll/GenericWrite/WriteDacl/WriteProperty/etc )具有写权限的用户都可以设置msDS-AllowedToActOnBehalfOfOtherIdentity(在其他形式的委派中,您需要域管理员特权)。

攻击结构

如果您对计算机帐户具有等效的写入权限,则可以获得该计算机的特权访问权限

假设攻击者已经在受害计算机上写入了等效的权限

  • 1 .攻击者破坏具有SPN创建一个(“服务 A”)的帐户。请注意,没有任何其他特殊权限的任何管理员用户最多可以创建10 个计算机对象 ( MachineAccountQuota)并为它们设置一个SPN 。因此,攻击者只需创建一个 Computer 对象并设置一个 SPN。
  • 2 .攻击者滥用其对受害计算机 (ServiceB) 的 WRITE 特权来配置基于资源的约束委派,以允许 ServiceA 冒充该受害计算机 (ServiceB) 的任何用户。
  • 3 .攻击者使用 Rubeus 为具有服务 B特权访问权限的用户执行从服务 A 到服务 B的完整 S4U 攻击(S4U2Self 和 S4U2Proxy) 
    • 1 .S4U2Self(来自 SPN 受损/创建的帐户):向我请求管理员的 TGS (不可转发)。
    • 2 .S4U2Proxy:使用之前步骤中不可转发的TGS管理员请求TGS受害者主机
    • 3 .即使您使用的是不可转发的 TGS,因为您正在利用基于资源的约束委派,它也会起作用。
  • 4 .攻击者可以传递票据冒充用户来访问受害者 ServiceB 

要检查您可以使用的域的MachineAccountQuota :

获取域 TGT

我要滥用基于资源的约束委派。首先,我将在我控制的域中添加一台假计算机。然后我可以作为 DC 为假计算机请求 Kerberos 票证,从而能够模拟其他帐户,如管理员。为此,我需要一个可以将机器添加到域中的经过身份验证的用户(默认情况下,任何用户最多可以添加 10 个)。这是在ms-ds-machineaccountquota属性中配置的,它需要大于 0。最后,我需要对加入域的计算机(GenericALL在 DC 上得到我)的写入权限。

我需要三个脚本来完成这次攻击:

  • PowerView.ps1
  • PowerMad.ps1
  • Rubeus.exe (来自SharpCollection的预编译 exe )

上传工具

上传这些工具到目标机器中。

upload /home/kali/PowerSploit/Recon/PowerView.ps1

1673342437_63bd2de5e9b0e3f65dfe0.png!small?1673342438911

将这些工具都上传好之后。

1673342451_63bd2df316be0beadb8bb.png!small?1673342451580

Winserver2012(DC)

验证环境

我需要知道 DC 上的管理员,Bloodhound 告诉我是 administrator@support.htb:

1673342470_63bd2e06a48c3970fbe95.png!small?1673342471295

验证用户是否可以将机器添加到域中:

1673342480_63bd2e10c63e5614b06d2.png!small?1673342481273

发现其设置为默认值 10,确保环境中有 2012+ DC:

1673342497_63bd2e2171f59e844f5db.png!small?1673342498018

提权攻击

我们首先需要连接到“dc.support.htb”服务器;使用相同的 Evil-WinRM 会话连接。连接后,将我们需要的两个工具上传到服务器上,Powermad和Rubeus。上传后,我们将执行以下操作。

服务器端

  1. 将新的假计算机对象添加到 AD。
  2. 将新的假计算机对象设置为具有约束委派权限。
  3. 为新的假计算机生成密码哈希。

创建一个计算机

使用 PowermadNew-MachineAccount来创建一台假计算机:

New-MachineAccount -MachineAccount (Get-Variable -Name "FakePC").Value -Password $(ConvertTo-SecureString '123456' -AsPlainText -Force) -Verbose

1673342510_63bd2e2e6e3564573bb36.png!small?1673342511193

1.使用内置 AD 模块,给新的假计算机对象 Constrained Delegation 权限

2.使用内置 AD 模块,检查最后一个命令是否有效。

Set-ADComputer (Get-Variable -Name "targetComputer").Value -PrincipalsAllowedToDelegateToAccount ((Get-Variable -Name "FakePC").Value + '$')
Get-ADComputer (Get-Variable -Name "targetComputer").Value -Properties PrincipalsAllowedToDelegateToAccount

1673342522_63bd2e3a99f6b292de79d.png!small?1673342523206

./r.exe hash /password:123456 /user:FAKE01$ /domain:support.htb

1673342534_63bd2e46a3c9b177656cf.png!small?1673342535599

解压我们要用到的工具。

1673342544_63bd2e50835ef42e903e6.png!small?1673342545033

攻击系统端

我们已经利用了这个安全漏洞,并赋予计算机对象“FAKE01”冒充另一台计算机。因此,我们向“dc.support.htb”上的资源请求一个新的 Kerberos Ticket-Granting-Ticket(TGT)。

1673342558_63bd2e5e6fb4be46ff631.png!small?1673342559360

获取管理员权限

使用impacket工具获取管理员权限,我们成功获取到管理员权限。

1673342569_63bd2e6907915c61d3324.png!small?1673342570105

获取root.txt

然后进入Desktop,获取到了root.txt

1673342582_63bd2e764432b587671d3.png!small?1673342582805

总结:

在整个过程中,用到了SMB文件共享和枚举、wireshark分析数据包、.net代码审计及ldAP密码恢复。基于资源的约束委派攻击和一些工具的使用,感兴趣的小伙伴可以尝试一下。

本文作者:pony686, 转自FreeBuf