ADSTALE-007: Orphaned Foreign Security Principals
- Platform
- Active Directory
- Category
- AD Stale & Obsolete Objects
- Severity
- Medium
- Zero Trust pillar
- Governance (weight 1)
- Golden fixtures
- 3
- Branch coverage
- Observed: fixtures prove the verdicts they exercise
- Provenance
- baseline
What it checks
The check binds to CN=ForeignSecurityPrincipals,DC=domain,DC=tld over LDAP and enumerates every child object of class foreignSecurityPrincipal. For each FSP it reads: - objectSid (the binary SID the placeholder represents) - cn (which is the SID rendered as a string, for example S-1-5-21-1004336348-1177238915-682003330-512) - memberOf (every group in the local domain that references this FSP) - whenCreated It then tries to resolve the SID in this order: (1) well-known SID table (S-1-5-* well-knowns, BUILTIN, NT AUTHORITY); (2) LookupAccountSid against the local DC, which transparently chases trust paths; (3) explicit bind through every outbound or bidirectional trust returned by Get-ADTrust. If all three fail, the FSP is marked orphaned. The check also classifies the failure mode: trust-removed (the SID prefix matches a domain SID for which no trustedDomain object exists), account-deleted (the trust is still present but the RID does not resolve), or unknown-authority (the SID does not match any reachable authority). Orphaned FSPs that are members of privileged groups (Domain Admins, Enterprise Admins, BUILTIN\Administrators, any group enumerated by AdminSDHolder) are escalated in severity.
Why it matters
Orphaned FSPs are a low-noise indicator of three distinct problems. First, hygiene: a domain that has accumulated unresolvable SIDs in privileged groups has lost track of who actually has access, and least-privilege reviews become unreliable because the auditor cannot answer "who is this." Second, persistence cover: attackers know defenders ignore FSPs, and an attacker who controls a SID-History injection or who has compromised a remaining trusted domain can place a malicious SID into a sensitive group where it appears as a benign-looking orphan. Mimikatz sid::add and similar tooling write SID-History values that surface as FSPs in the trusting domain; if defenders treat every orphan as "just a stale trust," the malicious entry blends in. Third, lateral movement signal: an orphaned FSP whose SID prefix matches a domain that was supposedly decommissioned years ago is evidence that the trust teardown was incomplete, which often correlates with leftover trust accounts, stale krbtgt material, or unmanaged DCs in a sibling forest. None of these are remotely-exploitable on their own, but they each erode the integrity of the access model the rest of the security program depends on.
Attack path
1. Trust enumeration: the attacker enumerates trusts with nltest /trusted_domains, Get-ADTrust, or BloodHound (CollectionMethod Trusts) and identifies any trust where the trusting domain still has FSPs from the trusted side. 2. SID-History injection: with DA on a trusted forest (or via a compromised inter-forest trust where SID filtering is disabled, see ADTRUST checks), the attacker forges a TGT containing a SID-History value that points to Domain Admins of the target domain. When the ticket is presented, the KDC accepts the SID-History entry and the principal appears in the target as a foreign principal. 3. FSP planting: alternatively, with WriteMember on a local group, the attacker adds a raw SID string for a controlled (or fabricated) external principal. AD silently materializes the FSP placeholder in CN=ForeignSecurityPrincipals. Because the cn is just a SID, defenders eyeballing group membership see a generic foreign entry rather than a named account. 4. Blending: the attacker selects a SID whose domain prefix matches a long-dead trust so the entry looks like decay rather than implantation. Defenders who run no FSP audit (or who write off all FSPs as stale) never investigate. 5. Use: when the attacker re-authenticates with the corresponding ticket or as the trusted principal, the local KDC honors the group memberships granted via the FSP, including Domain Admins if it was placed there. Because the FSP is the access vector, rotating local passwords does nothing; only removing the FSP from the group breaks the path. 6. Persistence audit gap: because most AD audit tooling reports group memberships by resolved name and silently drops unresolvable SIDs, the malicious membership is invisible in standard reports. Only a tool that walks CN=ForeignSecurityPrincipals directly (this check) surfaces the entry.
How Guerrilla assesses it
Guerrilla queries CN=ForeignSecurityPrincipals,<domainDN> with an LDAP filter of (objectClass=foreignSecurityPrincipal) and requests the attributes objectSid, cn, memberOf, whenCreated, and distinguishedName. For each returned object it constructs a System.Security.Principal.SecurityIdentifier from the binary objectSid and calls .Translate([System.Security.Principal.NTAccount]) inside a try/catch. Translation that throws IdentityNotMappedException is the orphan signal. The check also enumerates Get-ADTrust -Filter * and builds a map of trusted domain SIDs so it can label the failure mode (trust-removed vs account-deleted vs well-known-orphan such as the S-1-5-7 ANONYMOUS LOGON case). Each finding includes the FSP distinguishedName, the unresolvable SID string, the list of groups in memberOf, the inferred failure mode, and a privileged-group flag set when any entry in memberOf intersects the AdminSDHolder-protected set. The check is read-only, requires only Authenticated Users level access, and runs in seconds even on forests with thousands of FSPs because it batches the LDAP query with a paged search.
Recommended value
No orphaned Foreign Security Principals with unresolvable SIDs in the domain
Remediation
Enumerate all objects in CN=ForeignSecurityPrincipals and attempt to resolve each SID to a name using the corresponding trust. Identify FSPs where the SID cannot be resolved (trust removed or account deleted). Remove orphaned FSPs from any group memberships. Delete the orphaned FSP objects. Review remaining FSPs to verify the trust relationship and referenced accounts are still valid
Fixture-proven verdicts
Every verdict below is proven by a golden fixture in the module's gating test suite. This table derives from the last green run; it cannot be edited by hand.
| Scenario | Expected verdict |
|---|---|
| clean | PASS |
| known-bad | WARN |
| throttled | Not Assessed |
Framework mappings
- NIST SP 800-53
- AC-2
- CIS AD Benchmark
- 9.4.1