导语:信任天启——利用SID跳出林内信任 这是我在过去几年在安全方面学到的最喜欢的技能之一。就像大多数人第一次记住 Mimikatz能从内存中提取明文密码一样,我至今记忆犹新。 在2015年6月,我在本杰明·德比(Benjamin Delpy)的推特上看到了令人
信任天启——利用SID跳出林内信任
这是我在过去几年在安全方面学到的最喜欢的技能之一。就像大多数人第一次记住 Mimikatz能从内存中提取明文密码一样,我至今记忆犹新。
在2015年6月,我在本杰明·德比(Benjamin Delpy)的推特上看到了令人兴奋的内容,起初我并不了解其中的含义:
与本杰明聊天交流后,我确认了我的想法,他的回答是“对不起你的头:)”
这都要归功于 本杰明和 梅特卡夫(Sean Metcalf)为了让黄金票证更加“金黄”而努力付出的工作。2015年8月,我在博客上发表了一篇题为“信任天启” 的文章。
在此之前,我们的策略是映射出外部用户/组成员身份,并且从子域的信任“手工”跳转到林根域,这种情况往往是在拥有很多域的大网络环境中比较艰苦的过程。如“信任攻击策略”部分所述,由于“企业管理员”组的存在,因此我们总是将信任解释为从林根域到子域的“向下流动”。然而,微软多年来一直表示“林是Active Directory的安全边界”,自2005年以来,有安全研究人员已经发现了一个针对林内域的攻击。
但首先,为了使这一点完全合理,我必须解释sidHistory 和SID过滤安全机制,以及这对林中的域来说又有着什么样的意义。
sidHistory 是与Windows 2000 Active Directory一起添加到Windows中的,旨在帮助用户从一个域迁移到另一个域。如果用户被迁移,则可以选择将其原来旧的安全标识符(SID)以及之前所属任何组的SID添加到其新用户帐户的sidHistory属性中。当新用户尝试访问资源时,“如果SID或SID历史记录匹配,则根据ACL中指定的访问权限授予或拒绝访问资源。“意思是说,在用户的sidHistory属性中设置的任何组或旧用户SID授予他们访问权限,就好像他们是这些用户或这些组的成员一样。
由于信任在Active Directory林中工作原理的原因,sidHistory属性(PAC中的“ExtraSids”)在林的域内比较重要,因为这些SID在“SID筛选”保护的跨域引用中未被滤除掉。因此,将其sidHistory 或 ExtraSids设置为“Enterprise Admins”SID(仅存在于林根中的域用户组)的子域中的任何用户将有效地工作,就好像他们是企业管理员一样。正如微软已经知道这是一个问题,而且至少从 2005年的ITPro Windows文章以及几乎可以肯定之前的知识已经完全公开,sidHistory 是一个非常难以修改的受保护的属性。
以前,滥用这个过程是一个相当复杂的过程,包括修改关联域的Active Directory数据库(ntds.dit)中的sidHistory。关于更多的详细说明可以在 “SID过滤” 部分找到。
这就是为什么林是活动目录中的“信任边界”,而不是域!
Benjamin和Sean意识到,通过引入Mimikatz的“黄金票证”,攻击者可以随意设置为票证而创建的KERB_VALIDATION_INFO结构中的ExtraSids 部分(该结构“定义了由DC提供的用户登录和授权信息 ”)。所述的ExtraSids 部分被描述为“一个指向KERB_SID_AND_ATTRIBUTES结构列表的指针,该列表包含了对应于组而不是其主要所属的帐户域以外的域的SID”(该KERB_SID_AND_ATTRIBUTES结构的定义可以在这里找到。)
这意味着,如果攻击者拿到“域管理员”权限(或等同于实际上只是任何一个可以指向DCSync的帐户),那么他可以只需要5分钟的时间,就可以获取到林中的任何子域的KRBTGT哈希值并且可以将sid:<sid_of_enterprise_admins_in_forest_root> 添加到Mimikatz构造的票证中,而无需修改Active Directory数据库。这使攻击者有能力“跳跃”林信任关系,并危及林根域。
如果这是你第一次听到这个技巧,那我会像本杰明说的那样来一句:“对不起,:)”
对于我们的操作性的攻击策略,这意味着如果我们目前处于子域,并且可能危害DCSync 或DA访问,或者如果我们可以在攻击链的任何子域中拿到这个访问级别的权限,我们就可以放弃繁重的外部关系枚举,从而迅速地对林的根域发起入侵。我们在这个领域做到了这一点,是的,这真的是太棒了。:)对于具体的操作咨询和指导,请查看 我之前在2015年发表的Trustpocalypse文章。
这只适用于在林内的信任之间跳跃。由于SID过滤,这不适用于外部或林之间的信任,在本文的结尾部分:SID过滤 部分中将会有更详细的描述。
案例研究
所以,再考虑一下我们作为演示的信任图示:
假设我们在external.local中登录了一个帐户。由于sub.dev.testlab.local 信任 external.local ,因此external.local 可以从sub.dev.testlab.local 查询到信息,而SUB不能对EXTERNAL执行相同的操作。从外部上下文中,我们可以查询SUB具有的信任:
但是这只能返回sub.dev.testlab 与其他域(dev.testlab.local 和external.local )的直接信任关系。其实我们还可以从sub.dev.testlab 查询全局编录(不一定可以查询),并返回整个林中的所有域信任!
请注意,因为这是一个单向的非传递外部信任到sub.dev.testlab.local ,所以我们不能查询contoso.local 中来自EXTERNAL的上下文中的信任,因为我们的Kerberos通信不会被正确地引用。下图的内容就是这个错误通常意味着什么,如果你碰到过它的话:
所以,从这里我们将运行Get-DomainForeignGroupMember -Domain sub.dev.testlab.local 来查看SUB中包含的任何组是否包含了EXTERNAL中的成员:
从那里,我们将尝试有针对性的帐户入侵并跳转到sub.dev.testlab.local的信任。由于有关链接值复制和在“外部关系枚举”部分中描述的信任,所以Get-DomainForeignUser命令在这里是是没有用的。
然而,由于external.local – > sub.dev.testlab.local 是外部信任关系,并隐含了非传递性,所以无法查询的dev.testlab.local 或testlab.local域的本地组成员。
如果我们再能拿到sub.dev.testlab.local的域管理员(或同等权限)证书,那么根据“信任天启”部分中的描述,我们可以建立一个SID历史信任跳跃的黄金票证来入侵testlab.local 的林根域。如果我们无法获取提升的访问权限,我们将运行Get-DomainForeignUser 来查看是否有来自sub.dev.testlab.local的用户访问了林中的其他组。同样,请记住以前有关范围界定的信息,只有通用组的成员身份才会出现在这里:
我们还将运行Get-DomainForeignGroupMember -Domain dev.testlab.local 和Get-DomainForeignGroupMember -Domain testlab.local 来查看那些在其他林域中的组中具有“入站”访问权限的用户:
一旦我们利用之前描述过的任意一种方法拿到了部分或全部的testlab.local的林根域权限,我们会运行Get-DomainForeignGroupMember -Domain contoso.local和Get-DomainForeignGroupMember -Domain prod.contoso.local来看看TESTLAB林中是否有任何用户在CONTOSO林中拥有外部组成员资格。
在整个过程中,我们可以针对服务器(包括DC)来运行Get-NetLocalGroupMember <foreign,server>来查看是否有用户通过机器本地组越过了边界。我们还可以使用具有各种过滤器的目标Get-DomainObjectACL -Domain <foreign.domain> 来检查外部ACL成员资格。
或者我们可以用BloodHound把所有东西都搞出来,然后依靠模式来模拟跨林跳跃。:)