Active-Directory-Spotlights icon indicating copy to clipboard operation
Active-Directory-Spotlights copied to clipboard

Tree-Root trust incorrectly interpreted as CrossLink (Shortcut)

Open cnotin opened this issue 6 months ago • 1 comments

Hello @csandker,

Thanks for the trusts tooling and the https://systemsecurity.com/blog/active-directory-spotlight-trusts-part-2-operational-guidance/ article. I think I have found an error.

I have this setup in my lab with "lab.lan" and "labbis.lan" domains in a Tree Root trust. "lab.lan" remains the forest tree root Image

However, Enum-ADTrusts.ps1 sees them as CrossLink (Shortcut) instead:

### Legend ###
Flavor (F):
-- TreeRoot (TR)
-- ParentChild (PC)
-- CrossLink (CL)
[...]

               F: CL
               T: E
               AL: FWA
               SIDF: D
               TGTD: E
  + - - - - - - - - - - - - +
  '                         v
+------------+  F: CL     +---------------------+
|            |  T: E      |                     |
|            |  AL: FWA   |                     |
| labbis.lan |  SIDF: D   |       lab.lan       |
|            |  TGTD: E   |                     |
|            | <- - - - - |                     | <+
+------------+            +---------------------+  '
                            '                      '
[...]

I believe the issue comes from this part of the article:

If they're not parent and child we can check if the two entities have the same rootDomainNamingContext and if that's the case we have a Shortcut relationship (aka. CrossLink) and if not we have a TreeRoot relationship.

which translates to this code: https://github.com/sse-secure-systems/Active-Directory-Spotlights/blob/a1ee64d3a6c5ee494190eadae2c1ab932d27f7eb/AD-Trusts/Enum-ADTrusts.ps1#L823-L836

As you can see, the rootDomainNamingContext from both sides is identical and equal for these two domains with a tree-root trust:

  • from lab.lan
Dn: (RootDSE)
[...]
defaultNamingContext: DC=lab,DC=lan; 
dnsHostName: DC.lab.lan; 
[...]
rootDomainNamingContext: DC=lab,DC=lan; 
[...]
  • from labbis.lan
Dn: (RootDSE)
[...]
defaultNamingContext: DC=labbis,DC=lan; 
dnsHostName: DC4.labbis.lan; 
[...]
rootDomainNamingContext: DC=lab,DC=lan; 
[...]

Also, two domains who share a CrossLink (Shortcut) trust also have the same rootDomainNamingContext, so unfortunately that's not a heuristic we can use.

Let me know what you think.

cnotin avatar Sep 25 '25 16:09 cnotin

Hey @cnotin,

first of all: Sorry for the delayed reply. Thank you for reaching out, great spot and thanks again for your detailed report (this really helped to speed up the review).

You absolutely right about the erronous statement in the blog AND the incorrect code. I reviewed the implementation and I think I found my previous error and fixed my code. Unfortunately I have no longer access to the blog OR the original repository. Therefore I've forked the code here:

https://github.com/csandker/Enum-ADTrusts

Could you re-run this in your environment and let me know if this solves the issue?

csandker avatar Oct 11 '25 21:10 csandker

Hi! My turn to apologize for the delayed response 🙇‍♂️ Thank you for taking a look. I ran the updated script from your fork and I confirm that it correctly see the same tree-root trust as such:

### Legend ###
Flavor (F):
-- TreeRoot (TR)
-- ParentChild (PC)
-- CrossLink (CL)
[...]

  +--------------------------------------+  F: TR     +------------+
  |                                      |  T: E      |            |
  |                                      |  AL: FWA   |            |
  |               lab.lan                |  SIDF: D   | labbis.lan |
  |                                      |  TGTD: E   |            |
  |                                      | - - - - -> |            |
  +--------------------------------------+            +------------+

cnotin avatar Dec 03 '25 19:12 cnotin