【翻译】A short Introduction to BloodHound Custom Queries
在我的上一篇博客文章中,我已经展示了如何与 BloodHound CE 交互以及使用一些 Cypher 查询来发现常见的错误配置。在这篇文章中,我们将介绍 BloodHound 自定义查询,用于发现 Active Directory 网络中的真实漏洞和错误配置。
Active Directory 在我们的企业网络渗透测试中扮演着非常重要的角色。在许多测试中,我们能够在短时间内成功入侵目标域。通常被利用的攻击路径相对简单,比如通过 ESC8 提升权限。然而,这些非常简单的攻击路径正变得越来越罕见。在渗透测试 Active Directory 时,BloodHound 是一个不可或缺的工具。在那些稍微困难的渗透测试中,BloodHound 帮助我们识别出其他更复杂且需要更多步骤的攻击路径。通过利用 BloodHound 的 Cypher 查询并对其进行修改,为我们(获取域管理员权限)和我们的客户(获取有关错误配置的详细信息)带来了良好的结果。这篇博文将讨论我们使用的一些自定义查询以及如何利用这些连接。
在我们的测试过程中,我们喜欢在获取域管理员权限之前和之后运行 SharpHound(如果可能的话)。这使我们能够从两个不同的角度查看域。首先是从普通用户账户的视角,然后是对 Active Directory 更全面的白盒视角。使用域管理员权限,我们可以看到 BloodHound 可以收集的更多可能信息,例如所有系统上的本地管理员权限、所有 RDP 权限和所有活动会话。有了这些信息,我们可以发现更多可能被利用的潜在攻击路径。这非常有用,因为我们可以识别特定用户的潜在攻击路径,例如从低级管理员到域管理员的路径。
实践示例
虽然 BloodHound 内置了一些有用的查询,而且编写简单查询并不困难,但是拥有自定义查询非常有用。这不仅加快了过程,而且还降低了在测试过程中忽略 Active Directory 某些方面的风险。在我们最近的每次测试中,我们都发现了一些新的和独特的东西。有时这只是一个单独无法利用的独特配置,但也有一些情况下,通过 BloodHound 发现特定配置而成功入侵域。
我们将讨论以下主题:
-
非活动对象 -
跨域组成员资格 -
本地管理员权限 -
受保护的用户 -
未标记的零层级路径
所有示例都是基于GOAD的实验室环境进行的,并进行了一些修改。
非活动对象
在我们看到的许多环境中,Active Directory 都具有相当长的历史。旧的 Active Directory 对象可能被禁用和/或放在单独的 OU 中,但会在 Active Directory 中保留多年。我们经常发现具有非常弱密码的测试用户或退役的服务账户,这些账户长期未被使用但仍然处于活动状态。这些被遗忘的账户可能被攻击者利用,因为它们通常具有某种对攻击者有利的权限。此外,在某些情况下,入侵其他用户的唯一方法是重置他们的密码,因此这些非活动对象可以被利用,因为影响环境的风险要小得多。以下两个条件可以添加到现有查询中,以过滤活动/非活动对象:
非活动对象
u.lastlogon < (datetime().epochseconds - (90 * 86400)) AND u.lastlogontimestamp < (datetime().epochseconds - (90 * 86400))
活动对象
(c.lastlogon > (datetime().epochseconds - (30 * 86400)) OR c.lastlogontimestamp > (datetime().epochseconds - (30 * 86400)))
必须同时使用 lastlogon 和 lastlogontimestamp 这两个属性才能获得准确的时间戳。它们代表两个不同的时间:在查询的域控制器上的最后登录时间,以及通过复制获得的在其他域控制器上的最后登录时间。这两个条件可以添加到任何 Cypher 查询中,以进一步过滤结果。例如:如果我们能够从域控制器中导出 NTDS.DIT 并破解一些密码。为了进一步提高这个发现对客户的价值,我们可以使用 BloodHound 生成根据特定条件过滤的项目列表,比如非活动用户(在最近 n 天内没有登录)。这对客户来说非常有用,可以直接看到有多少活动用户使用弱密码,或者有多少未使用的账户可能容易被攻破。要生成这样的列表(可用于从已破解的 NTDS.DIT 中筛选用户,或作为受影响资源的列表提供给客户),必须使用 BloodHound API 或 neo4j(直接使用或通过 Web 界面)。
非活动用户(90 天内未登录)
MATCH (u:User) WHERE u.lastlogon < (datetime().epochseconds - (90 * 86400)) AND u.lastlogontimestamp < (datetime().epochseconds - (90 * 86400)) AND u.samaccountname <> 'krbtgt' AND u.enabled = trueRETURN u
使用不受支持操作系统的活动计算机(最近 30 天内有登录)
MATCH (c:Computer) WHERE c.operatingsystem =~ '(?i).*(2000|2003|2008|2012|xp|vista|7|8|me).*' AND (c.lastlogon > (datetime().epochseconds - (30 * 86400)) OR c.lastlogontimestamp > (datetime().epochseconds - (30 * 86400))) AND c.enabled = true RETURN c
跨域组成员资格
在我们最近的一次渗透测试中,我们遇到了两个域:让我们称它们为域 A 和域 B。域 A 是新建的,并且在设计时就考虑了安全性。由于它是主要使用的域,我们将重点放在它上面。但是客户做得相当不错,我们在提升到域管理员权限方面没有取得太大进展。所以我们决定看看域 B。域 B 是之前使用的域,仍然用于一些服务和系统,但计划很快就要停用这个域。这也意味着这两个域之间存在信任关系。在域 B 中获取域管理员权限很快就实现了。在收集了两个域的 BloodHound 数据后,组合信息提供了一些有趣的发现。以下查询用于识别跨域组成员资格:
MATCH p=((u1:Group)-[r:MemberOf]->(u2:Group)) WHERE toLower(u1.domain) <> toLower(u2.domain) RETURN p
这个查询虽然不是最优的,但完成了任务。我们成功识别出域 B 中的一个组是域 A 中一个高权限组的成员。最终,我们通过利用这个跨域连接和一些其他漏洞成功入侵了域 A。类似的情况可以在 GOAD 中找到。
底部的两个集群是由于 sevenkingdoms.local 和 north.sevenkingdoms.local 域之间的父子信任关系造成的。而顶部的集群则不是默认的。我们可以完全展开所有跨域的嵌套组成员关系。这在识别目标用户时非常有用。以下查询返回通过嵌套组成员关系跨域的所有对象:
MATCH p=((n)-[r:MemberOf*1..]->(m:Group)) WHERE n.domainsid <> m.domainsidreturn p
这个查询通过使用 domainsid 而不是域名进行比较得到了改进。通过使用 domainsid,查询还可以返回那些未被其对应域收集的对象。我们使用域名的临时查询之所以有效,是因为我们收集了两个域的数据。根据域的大小,这个查询可能需要一些时间,但通过提供跨域边界的所有对象的详细列表,可以为客户带来好处。
本地管理员权限
BloodHound 中另一个有趣的可视化连接是本地管理员权限。为了收集必要的数据,我们需要对想要收集数据的系统拥有管理员权限。因此,以 DA 身份运行来收集所有数据、显示潜在的错误配置并揭示新的攻击路径是最有意义的。如果我们只能以普通用户身份运行 SharpHound,我们只能看到我们拥有本地管理员权限的系统的信息,或者只能看到很少几个系统的信息。如果我们只是想提升到 DA,这就足够了,但有了 DA 权限,我们可以更进一步,向客户展示更有价值的信息。
在最近的一次渗透测试中,我们通过滥用拥有其他计算机账户本地管理员权限的计算机账户成功获取了 DA 权限。结合其他错误配置(如缺少 SMB Signing),我们能够强制具有本地管理员权限的系统向目标系统进行身份验证并转储 SAM。使用本地管理员的密码哈希,我们能够转储 LSASS 进程并继续我们获取 DA 的路径。
以下查询可用于识别两个计算机对象之间的这些连接:
MATCH p=(m:Computer)-[:AdminTo]->(n:Computer) RETURN p
这可能看起来是一个奇怪的配置,但某些软件解决方案需要它,例如 SCCM。在 SCCM 中,站点服务器在站点系统上具有本地管理员权限(参考 Misconfiguration-Manager: ELEVATE-1)。在计算机对象不是直接拥有管理员权限而是通过组获得权限的情况下,这也可以被修改以包含组成员资格。但是,对于这次攻击,我们将专注于直接连接。最终结果可能如下所示(默认情况下不包含在 GOAD 中):
这意味着我们可以强制从 meereen 进行身份验证并将其中继到 braavos,以获得 braavos 上的本地管理员访问权限。唯一的要求是 braavos 上禁用了 SMB signing。
使用的系统如下:meereen (xx.xx.xx.62)、braavos (xx.xx.xx.64)、attacker (xx.xx.xx.65)
我们可以使用多种强制方法来执行此攻击。这里我们使用 printerbug。
可以使用 ntlmrelayx 将强制的身份验证中继到 braavos,以读取 SAM 数据库。
转储的本地管理员哈希可用于访问系统并转储 LSASS 进程,以获取域用户的哈希值。
Protected users
我们经常发现的一个缺失的加固措施是高权限用户没有被加入 protected users 组。此组中的用户具有额外的凭据盗窃保护措施,例如禁用这些用户的 NTLM 身份验证或限制 Kerberos 票据的有效期。以下代码片段返回所有被标记为 Tier Zero 且不在 protected users 组中的用户:
MATCH (u1:User)-[:MemberOf*0..]->(g1:Group) WHERE g1.objectid ENDS WITH'-525'WITHCOLLECT(u1) AS exclude1 MATCH (u:User)WHERE u.system_tags = 'admin_tier_0'ANDNOT u IN exclude1RETURN u
返回的用户可以提供给客户,以便将缺失的管理用户添加到此组中。此外,这个查询可以集成到其他查询中进行进一步筛选。一个很好的用例是搜索所有活动会话并过滤掉所有受保护的用户。通过这种方式,我们可以找到所有可以转储哈希值并使用 pass-the-hash 进行身份验证的活动会话。以下查询使用 targets 变量中未受保护的 tier zero 用户,并用它来筛选所有活动会话:
MATCH (u1:User)-[:MemberOf*0..]->(g1:Group) WHERE g1.objectid ENDS WITH'-525'WITHCOLLECT(u1) AS exclude1 MATCH (u:User) WHERE u.system_tags = 'admin_tier_0'ANDNOT u IN exclude1WITHCOLLECT(u) AS targets MATCH p=(n:User)<-[:HasSession]-(c:Computer)WHERE n IN targetsRETURN p
然而,需要注意的是,仍然可以滥用受保护用户的活动会话。
通向未标记 Tier Zero 的路径
在 Active Directory 环境中,通常存在具有多种权限的服务,这些服务可以用于提升权限,例如 Exchange、WSUS、SCCM 或 CA。所有这些服务和系统都可能被用来破坏高价值目标,因此对攻击者来说很有价值。例如,如果攻击者成功破坏了 Certificate Authority (CA),他们就可以伪造任何证书并以域管理员身份进行身份验证。以下查询显示了从非 Tier Zero 对象破坏 CA 的最短路径。对于较大的域,可能需要添加限制。
MATCH p=shortestPath((n)-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl| MemberOf|ForceChangePassword|AllExtendedRights|AddMember|Contains|GPLink| AllowedToDelegate|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM| HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword| SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword| WriteAccountRestrictions*1..]->(ca:EnterpriseCA)) WHERE (n.system_tags <> 'admin_tier_0' or n.system_tags IS NULL) and n.objectid <> 'S-1-5-32' and not n:OU and not n:Container and n <> caRETURN p
在 where 子句中,结果经过过滤和清理,只返回非 Tier Zero 的起始节点,并过滤掉一些起始点,如 OU 或 Container,因为这些本身不能真正作为攻击的起始点。
这张图显示了有多种方式可以破坏 CA。假设我们正在进行一次渗透测试,已经成功破坏了用户[email protected]。我们通过在之前的查询中添加{system_tags: 'owned'}作为起始条件,来寻找从我们已破坏的对象到 CA 的路径。
MATCH p=shortestPath((n {system_tags:'owned'})-[:Owns|GenericAll|GenericWrite|WriteOwner|WriteDacl| MemberOf|ForceChangePassword|AllExtendedRights|AddMember|Contains|GPLink| AllowedToDelegate|AllowedToAct|AdminTo|CanPSRemote|CanRDP|ExecuteDCOM| HasSIDHistory|AddSelf|DCSync|ReadLAPSPassword|ReadGMSAPassword|DumpSMSAPassword| SQLAdmin|AddAllowedToAct|WriteSPN|AddKeyCredentialLink|SyncLAPSPassword| WriteAccountRestrictions*1..]->(ca:EnterpriseCA)) WHERE (n.system_tags <> 'admin_tier_0' or n.system_tags IS NULL) and not n:OU and not n:Container and n <> caRETURN p
此查询返回了以下路径。我们已经破坏的用户是另一个域中某个组的成员组的成员。该组在另一个域中拥有高权限,允许我们更改计算机对象 braavos 的 Active Directory 属性,而 braavos 就是 CA。这可以用来添加 shadow credentials 来接管 CA。一旦攻击者成功破坏了 CA,整个域也可能被破坏。
在我们的场景中,第一步是使用pywhisker向 braavos 计算机对象添加 shadow credentials。之后可以从 DC 请求计算机账户的 TGT 和 hash 值。
最后一步是使用 Kerberos S4U2self 功能获取本地管理员权限并创建 CA 的备份。然后可以使用 CA 的私钥创建任意证书,包括域管理员的证书,这些证书可用于身份验证。
结论
总而言之:自定义查询不仅加快了分析 BloodHound 数据的过程,还允许我们过滤数据以获得我们确切需要的内容。对于我们攻击者来说,这可以帮助我们提高效率并更容易找到独特的攻击路径。对于我们的客户来说,数据可以以一种直接回答他们特定问题的方式呈现,例如哪些用户受到特定攻击/配置错误的影响。
我希望这篇博文为您提供了关于如何使用自定义查询来充分利用 BloodHound 的简要概述,并且展示的一些查询对您的用例有用。如果您自己想出了自定义查询,欢迎联系并分享!
原文始发于微信公众号(securitainment):BloodHound 自定义查询简介
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论