ADPRIV-009: Nested Group Membership Analysis
- Platform
- Active Directory
- Category
- AD Privileged Account Security
- Severity
- High
- Zero Trust pillar
- Identity (weight 2)
- Golden fixtures
- 3
- Branch coverage
- Observed: fixtures prove the verdicts they exercise
- Provenance
- baseline
What it checks
The check resolves a curated set of privileged groups by well-known SID and by name, including: - Domain Admins (S-1-5-21-<domain>-512) - Enterprise Admins (S-1-5-21-<root>-519) - Schema Admins (S-1-5-21-<root>-518) - Administrators (S-1-5-32-544) - Account Operators (S-1-5-32-548) - Backup Operators (S-1-5-32-551) - Server Operators (S-1-5-32-549) - Print Operators (S-1-5-32-550) - DnsAdmins, Group Policy Creator Owners, Cert Publishers, Pre-Windows 2000 Compatible Access, Protected Users, and any custom group flagged with adminCount=1 For each group the check reads the member attribute, then for every nested group it recurses depth-first, recording the path. The constructed attribute msDS-MembersOfGroupTransitive (and the symmetric msDS-MemberOfTransitive on principals) is consulted where available to cross-check the recursive walk. For every resolved leaf principal the check captures sAMAccountName, objectClass, objectSid, distinguishedName, the full nesting path used to reach the privileged parent, the nesting depth, and a circular-nesting flag. Foreign-security-principals from trusted domains are resolved across the trust where possible and otherwise flagged as opaque external members. The check also enumerates SID history on every leaf, because a non-member account with SID history that includes a privileged group SID is effectively a hidden member.
Why it matters
Nested groups are the single most common reason a published Domain Admins membership list understates the true Tier-0 population. A typical pattern: a Help Desk team is nested into Server Operators for a one-off task in 2014, Server Operators is nested into Administrators by default, Administrators on a domain controller is equivalent to Domain Admins for most practical attack purposes, and seven years later the Help Desk group has 200 members who all hold logon rights on every DC. None of those 200 users appear in net group "Domain Admins" /domain, so the access goes unnoticed in every quarterly access review. BloodHound was built specifically to expose this class of indirect privilege: its Shortest Path to Domain Admins query traverses MemberOf edges transitively and routinely surfaces multi-hop paths that the defender did not know existed. Attackers exploit nesting because it gives them low-friction targets: a phishing payload against a Help Desk technician is far easier than a payload against a named Domain Admin, and the resulting access is identical. Circular nesting (group A contains group B contains group A) compounds the problem by making any audit tool that does not detect cycles loop forever or quietly truncate, hiding the true membership behind a parse failure rather than a finding.
Attack path
1. Collection: from any authenticated user context the attacker runs SharpHound (SharpHound.exe -c Group,LocalAdmin,Session,Trusts,ACL) or BloodHound.py to ingest every group, every membership edge, and every session. The collector resolves MemberOf transitively and stores the result as a Neo4j graph. 2. Path discovery: in the BloodHound UI the attacker runs Shortest Path to Domain Admins from the currently owned principal, or the broader Find Principals with DCSync Rights query. The graph returns every multi-hop nesting path, including the nested-group chain that grants the indirect privilege. 3. Target prioritisation: the attacker filters the resulting paths by exploitability, preferring paths that traverse populated groups (a 200-member Help Desk group is far easier to phish than a 2-member Tier-0 group) and paths that include weakly defended principals (kerberoastable accounts, unconstrained delegation hosts, users with stale passwords). 4. Pivot: the attacker compromises any leaf principal in the chosen path through phishing, password spray, Kerberoasting, or AS-REP roasting. Because the privilege is granted transitively, no membership change is required on the attacker side. 5. Privilege exercise: once the attacker authenticates as the compromised leaf, Windows resolves the full transitive group membership during logon (Kerberos PAC or NTLM token build) and stamps the privileged SIDs into the access token. The attacker then performs DCSync, GPO modification, or direct DC logon as if they had been added to Domain Admins directly. 6. Persistence: the attacker adds themselves or a backdoor account to a deeply nested group several hops from Tier-0, betting that the defender will only audit the top-level privileged groups and miss the indirect path.
How Guerrilla assesses it
Guerrilla binds to a writable DC and, for each privileged group in the curated list, issues an LDAP search with the constructed attribute msDS-MembersOfGroupTransitive requested explicitly. Where the DC supports the constructed attribute, the result is the flattened transitive membership in one round trip. Where it does not (older functional levels or filtered DCs), the check falls back to a depth-first recursive walk in PowerShell that maintains a visited-set keyed by objectSid to detect and break cycles. For every leaf the check records the full chain of group DNs traversed from the privileged parent to the leaf, the nesting depth, the objectClass at every hop, and a flag for any cycle observed. Foreign-security-principals are resolved through the corresponding trust where the trust direction permits; unresolved FSPs are emitted with their raw SID and the trusted-domain SID prefix so the analyst can identify the source domain. SID history is read in the same LDAP call and any SID matching a known privileged group SID is flagged as a transitive grant outside the normal MemberOf graph. The findings are emitted as one row per (privileged group, leaf principal) pair with the path as a delimited string so the output can be filtered and pivoted in Excel or imported into BloodHound as a custom edge set.
Recommended value
All nested group paths to privileged groups documented. Maximum nesting depth of 2 levels. No circular nesting
Remediation
Recursively enumerate all privileged group memberships using Get-ADGroupMember -Recursive. Map all nesting paths and identify users who gain privileges through indirect membership. Flatten unnecessary nesting and document all remaining nested paths with business justification
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 | FAIL |
| throttled | Not Assessed |
Framework mappings
- NIST SP 800-53
- AC-6(1), AC-2
- ANSSI
- R4
- CIS AD Benchmark
- 4.2.1
- MITRE ATT&CK
- T1069.002, T1078.002