ADACL-001: Critical Object ACL Audit
- Platform
- Active Directory
- Category
- AD ACL & Delegation
- Severity
- Critical
- Zero Trust pillar
- Identity (weight 3)
- Golden fixtures
- 3
- Branch coverage
- Observed: fixtures prove the verdicts they exercise
- Provenance
- baseline
What it checks
For each critical object, the check reads the nTSecurityDescriptor attribute via LDAP and parses every ACE in the DACL. It evaluates ActiveDirectoryRights (GenericAll, GenericWrite, WriteDacl, WriteOwner, WriteProperty, ExtendedRight on User-Force-Change-Password / DS-Replication-Get-Changes / DS-Replication-Get-Changes-All), the IdentityReference of the trustee, and whether the ACE is inherited or explicit. The protected object set includes: - Domain Root (DC=domain,DC=tld) - CN=AdminSDHolder,CN=System,DC=domain,DC=tld - CN=Schema,CN=Configuration,DC=domain,DC=tld - CN=Configuration,DC=domain,DC=tld - OU=Domain Controllers,DC=domain,DC=tld Trustees outside the default set (Domain Admins, Enterprise Admins, SYSTEM, BUILTIN\Administrators, the well-known Pre-Windows 2000 group on legacy objects, and Enterprise Domain Controllers) holding rights that permit modification are reported as findings. AdminSDHolder is given special weight because its ACL is propagated to every protected account hourly by the SDProp process.
Why it matters
The objects audited by this check are the apex of the AD trust model. Modify rights on the Domain Root permit DCSync (replicating secrets for every account, including krbtgt) and arbitrary DACL changes anywhere below it. WriteDacl or GenericAll on AdminSDHolder turns into a persistent backdoor: SDProp will re-stamp the attacker ACE onto Domain Admins, Enterprise Admins, krbtgt, and every other protected principal every 60 minutes. Rights on the Schema partition allow the attacker to add attributes (including weaponized certificate template attributes) or alter mustContain on user / computer classes, which is a forest-wide and effectively irreversible change. Rights on the Configuration partition allow modification of sites, services, ADCS PKI objects, and Exchange configuration across the forest. Rights on the Domain Controllers OU allow GPO linking or computer object modification that compromises every DC. Because these primitives are trivial to chain into Tier-0 compromise, they are routinely staged by ransomware crews and state-aligned operators.
Attack path
1. Reconnaissance: the attacker enumerates DACLs on critical objects via BloodHound (SharpHound -CollectionMethod ACL,DCOnly) or PowerView (Get-DomainObjectAcl -SearchBase "DC=domain,DC=tld" -ResolveGUIDs). 2. Edge identification: BloodHound highlights GenericAll, WriteDacl, WriteOwner, AllExtendedRights, GetChanges, or GetChangesAll edges from a compromised principal to one of the critical objects. 3. Exploitation, AdminSDHolder branch: with WriteDacl on AdminSDHolder, the attacker adds an ACE granting their controlled account FullControl. Within one SDProp cycle (default 60 minutes) the ACE is mirrored onto Domain Admins, krbtgt, and every other protected group. The attacker now has a persistent path to Domain Admin that survives password resets of the compromised principal. 4. Exploitation, Domain Root branch: with GetChanges + GetChangesAll on the domain object, the attacker runs DCSync (mimikatz lsadump::dcsync, secretsdump.py, or impacket-secretsdump) to pull the krbtgt hash, forge Golden Tickets, and impersonate any principal in the forest. 5. Exploitation, Schema or Configuration branch: with write rights on the Configuration NC, the attacker modifies ADCS template ACLs (link to ESC4 / ESC5) or NTAuthCertificates to plant a rogue CA, achieving forest-wide authentication forgery. 6. Cleanup: ACEs are added with inheritance flags that blend with default permissions, and the attacker may rename the trustee or move it under an OU the defender does not audit.
How Guerrilla assesses it
Guerrilla resolves each critical objects distinguishedName, binds with Get-ADObject -Properties nTSecurityDescriptor, and walks the DACL via the .NET ActiveDirectorySecurity / DirectoryEntry surface. Every non-inherited ACE is compared against a baseline of expected trustees and rights. Inherited ACEs are checked against the parent owner. The check uses LDAP (not Get-Acl AD:\, which depends on the AD PSDrive) so it works against any reachable DC and does not require RSAT loaded locally. Trustees are resolved through the local DC LookupAccountSid / Translate(NTAccount) path so cross-domain SIDs in foreign trusts surface as SID strings rather than being silently dropped. Results are emitted with the DN, trustee, ActiveDirectoryRights, AccessControlType, IsInherited, and ObjectType GUID so downstream triage can map an ACE to its semantic meaning (for example, the DS-Replication-Get-Changes-All extended right GUID 1131f6ad-9c07-11d1-f79f-00c04fc2dcd2).
Recommended value
Only default and explicitly authorized ACEs on critical AD objects; no unexpected principals with modify or full-control access
Remediation
Review ACLs on critical objects using Get-Acl or dsacls.exe. Remove non-default ACEs that grant write, modify, or full-control permissions to unauthorized principals. Use AdminSDHolder to enforce consistent ACLs on protected groups. Document all intentional delegations.
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, AC-6(5), AU-6
- ANSSI
- vuln_permissions_adminsdholder
- MITRE ATT&CK
- T1222.001, T1003.006