← back to theory
AD

Domain and Forest Trusts

Organisations rarely have just one domain. Mergers, acquisitions, geographic separation, and administrative boundaries all lead to multiple domains and forests that need to share access. Trusts are the relationships that let a principal in one domain authenticate to resources in another. They are essential plumbing — and they are also the roads an attacker uses to move from a domain they own into one they do not.

What a trust actually is

A trust is an agreement that lets one domain's authentication authority vouch for its users to another domain. When domain A trusts domain B, users from B can be granted access to resources in A. The trust is backed by a shared inter-domain key, and Kerberos uses it to issue referral tickets that carry a user across the boundary.

The dimensions of a trust

PropertyMeaning
DirectionOne-way (A trusts B, so B's users can access A) or two-way (both). Trust flows opposite to access
TransitivityTransitive trusts extend through the chain — if A trusts B and B trusts C, A effectively trusts C
Intra-forestTrusts between domains in the same forest — automatic, two-way, and transitive
ExternalA trust to a domain in another forest — non-transitive by default
Forest trustA trust between two forest roots; transitive within each forest's domains
The direction trips people up: trust flows opposite to access. If domain A "trusts" domain B, it is B's users who gain access to A's resources. When you read a trust relationship, ask "whose users can reach whose resources?" rather than following the arrow literally.

The forest is the security boundary

This is the single most important fact about trusts, and it is worth repeating from the fundamentals page. Inside a forest, all domains trust each other automatically, transitively, and two-way, and they share the schema and configuration partitions. That means compromising any domain in a forest generally leads to compromising the whole forest — most directly via the Enterprise Admins group or by abusing the trust key between a child and the forest root.

A separate forest, with only an external or forest trust, is a genuine boundary — but only if it is configured with the protections below. A separate domain in the same forest is not a boundary at all.

SID history and SID filtering

The classic cross-boundary attack turns on two features. When a user moves between domains (say during a migration), their old SID can be preserved in the SID history attribute so they keep their old access. Windows honours SID history when making access decisions.

The abuse: if you can write SID history — or forge a ticket that includes it — you can insert the SID of a privileged group from the target domain (e.g. the target's Domain Admins or Enterprise Admins) into a principal you control. When that principal crosses the trust, the target treats it as a member of that privileged group.

SID filtering is the defence: it strips SIDs from outside the trusted domain out of tickets crossing the boundary, so an injected foreign privileged SID is discarded. Intra-forest trusts do not apply SID filtering by default (they are meant to be a single trust zone), which is again why the forest, not the domain, is the real boundary. External and forest trusts should have it enabled — and when they do not, the cross-forest path opens up.

Cross-boundary attack paths

ScenarioTechnique
Child domain → forest rootForge an inter-realm ticket with the trust key and inject the root's Enterprise Admins SID (intra-forest, no SID filtering)
Extract the trust keyDCSync the trust account (<domain>$) to get the inter-domain key
Cross external trust with weak filteringInject a foreign privileged SID via SID history if filtering is disabled
Foreign group membershipUsers/groups from a trusted domain that have been granted rights in the target — legitimate but often over-broad
Kerberoast across a trustRequest service tickets for SPNs in a trusted domain and crack them locally
# enumerate trusts
netexec ldap dc01 -u jdoe -p pass -M enum_trusts
# PowerView
Get-DomainTrust -Domain corp.local
# BloodHound maps trusts and cross-domain ACL/group edges visually

# child-to-parent via trust key + SID history (conceptual)
ticketer.py -nthash <trust_key> -domain-sid <child_sid> \
  -extra-sid <root_sid>-519 -domain child.corp.local Administrator

Detection and defence

ControlEffect
Enable SID filtering on external/forest trustsDiscards injected foreign SIDs — the core cross-forest defence
Enable selective authenticationRequires explicit per-resource grants for cross-trust access rather than blanket authenticated-users access
Audit SID historyLegitimate only during migrations; lingering or unexpected SID history is a finding
Minimise and review trustsRemove trusts that are no longer needed; each one is an attack surface
Treat the forest as one blast radiusDo not rely on domain separation for isolation; use separate forests for genuinely separate security zones

The takeaway

Trusts let identity cross domain and forest boundaries, and attackers ride them in the same direction access flows. Within a forest there is effectively no boundary at all — own one domain and the forest is reachable, because intra-forest trusts are automatic, transitive, and unfiltered. Across forests, the boundary holds only when SID filtering and selective authentication are configured; where they are not, SID history injection and trust-key forgery carry privilege across. Map trusts early with BloodHound or PowerView, understand which are intra-forest versus external, and remember that the forest is the unit of compromise. The key-extraction step relies on DCSync, and the ticket forging on ticket attacks.

Related reading