An Extra ACE on AdminSDHolder Silently Grants Control Over Every Protected AD Account
An ACE added to AdminSDHolder for a low-privilege automation account was propagated by SDProp to every protected AD group member, granting silent domain-wide admin control.
Operational summary
At a glance
- Symptom
- A break-glass automation account with no membership in Domain Admins, Enterprise Admins or any other protected group can reset the password and modify group…
- Likely cause
- Active Directory protects members of built-in privileged groups — Domain Admins, Enterprise Admins, Administrators, Schema Admins, Account Operators, Backup Operators and several others —…
- Impact
- The automation account gained an effective, standing Domain Admin-equivalent capability across the domain without ever appearing inside a privileged group, evading every control that audits privilege through group…
- Verification signal
- Confirm both that the ACE is gone from AdminSDHolder and that it does not reappear on protected accounts after the next propagation cycle.Re-run the read-only ACL listing on…
- Safe correction
- Remove the unauthorised access control entry from the AdminSDHolder object itself; removing it only from downstream protected accounts is not a fix, because the next SDProp cycle simply…
- Rollback or recovery
- If removing the ACE breaks a dependency that was not identified during diagnosis, restore the exact before-change ACL captured during correction rather than reconstructing it from memory.Reapply the…
Symptom
A break-glass automation account with no membership in Domain Admins, Enterprise Admins or any other protected group can reset the password and modify group membership of a genuine Domain Admin object, even though no delegated permission was ever granted on that user object, its parent organisational unit, or any group the account belongs to.
The anomaly typically surfaces during a routine privileged access review: an auditor lists direct and inherited permissions on a small set of Tier-0 accounts and finds an unexplained Full Control access control entry (ACE) attributed to a low-privilege service principal with no obvious delegation trail.
False Assumption
The team that created the automation account had granted it Full Control directly on the AdminSDHolder object inside CN=System, reasoning that AdminSDHolder is an inert template object used only internally by Active Directory and unrelated to any live user or group. Because the object held no group memberships and appeared in no delegation report tied to an actual privileged principal, the change looked contained and reversible.
Root Cause
Active Directory protects members of built-in privileged groups — Domain Admins, Enterprise Admins, Administrators, Schema Admins, Account Operators, Backup Operators and several others — through a background process commonly referred to as SDProp (Security Descriptor Propagator). On a recurring cycle, SDProp copies the security descriptor of the AdminSDHolder object onto every current member of those protected groups, disables permission inheritance on each protected object, and stamps adminCount=1 to mark it as protected.
Because SDProp treats AdminSDHolder as the authoritative template for every protected object’s access control list, any ACE added to AdminSDHolder — deliberately or by mistake — is propagated to every protected account on the next cycle, not just to the object the change appears to affect. The automation account’s Full Control grant on AdminSDHolder was never scoped to that single object; it was silently rebroadcast to the entire Tier-0 population of the domain.
Impact
The automation account gained an effective, standing Domain Admin-equivalent capability across the domain without ever appearing inside a privileged group, evading every control that audits privilege through group membership: conditional access policies scoped to Domain Admins, privileged access management checkout workflows, and periodic group membership reviews. Only an ACL-level review of AdminSDHolder or the protected accounts themselves would surface the grant, and because SDProp reasserts the ACL on its own cycle, stripping the ACE from one affected account only made the exposure look self-healing in the wrong direction.
Diagnosis
Confirm the exposure before changing anything. Two checks establish whether AdminSDHolder carries an unexpected ACE and whether it has already propagated:
- List the access control list on the AdminSDHolder object directly and compare every trustee against a documented list of intended delegations.
- Enumerate accounts flagged with
adminCount=1, including accounts no longer in a protected group, since SDProp does not automatically clear that flag when membership changes.
# Read-only: list ACEs on the AdminSDHolder object
Get-Acl "AD:CN=AdminSDHolder,CN=System,DC=corp,DC=example" |
Select-Object -ExpandProperty Access |
Format-Table IdentityReference, ActiveDirectoryRights, AccessControlType -AutoSize
# Read-only: find every account currently or previously marked protected
Get-ADUser -Filter {adminCount -eq 1} -Properties adminCount, memberOf |
Select-Object SamAccountName, adminCount, memberOf
Cross-reference every unexpected trustee against change records and known automation accounts. Treat any trustee that cannot be attributed to a documented, currently valid requirement as unauthorised until proven otherwise.
Correction
Remove the unauthorised access control entry from the AdminSDHolder object itself; removing it only from downstream protected accounts is not a fix, because the next SDProp cycle simply reapplies it from the template. Capture the full existing ACL before making any change, so the prior state can be restored precisely if the removal affects a legitimate dependency.
# Evidence capture before change (read-only)
Get-Acl "AD:CN=AdminSDHolder,CN=System,DC=corp,DC=example" |
Select-Object -ExpandProperty Access |
Export-Csv adminsdholder-acl-before-change.csv -NoTypeInformation
# State-changing: remove the specific unauthorised ACE (adjust trustee name)
$acl = Get-Acl "AD:CN=AdminSDHolder,CN=System,DC=corp,DC=example"
$ace = $acl.Access | Where-Object { $_.IdentityReference -like "CORPsvc-automation*" }
$acl.RemoveAccessRule($ace) | Out-Null
Set-Acl "AD:CN=AdminSDHolder,CN=System,DC=corp,DC=example" -AclObject $acl
Stop before running the removal if the exported before-snapshot could not be produced, or if any documented automation still depends on the trustee being present; escalate to the Active Directory security owner rather than removing the ACE unverified.
Validation
Confirm both that the ACE is gone from AdminSDHolder and that it does not reappear on protected accounts after the next propagation cycle.
- Re-run the read-only ACL listing on AdminSDHolder and confirm the trustee no longer appears.
- Sample one protected account, ideally a test account used only for this check, after one full propagation interval and confirm no residual ACE for the removed trustee.
The propagation interval and any on-demand trigger available in your environment vary by Windows Server version and domain functional level; confirm both against current Microsoft documentation for your deployed version before relying on a specific wait time or manual trigger method.
Rollback
If removing the ACE breaks a dependency that was not identified during diagnosis, restore the exact before-change ACL captured during correction rather than reconstructing it from memory.
- Reapply the access control entries recorded in the pre-change export to the AdminSDHolder object.
- Re-verify the restored ACL matches the captured snapshot exactly before considering the rollback complete.
- Reopen the review with the owning team to decide whether the original grant should be re-scoped to a narrower object instead of AdminSDHolder, rather than restoring it unchanged long-term.
Prevention
Treat AdminSDHolder as a Tier-0 object under the same change control as Domain Admins itself, not as an internal implementation detail.
- Require a documented change ticket and second-person review for any ACL modification on AdminSDHolder or the System container.
- Enable auditing on AdminSDHolder so that ACL changes generate an alert rather than being discovered during a manual review.
- Alert on new or changed
adminCount=1flags, since this attribute is a reliable signal that SDProp has touched an object. - Ensure privileged access reviews inspect access control lists on Tier-0 objects directly, rather than relying solely on group membership reports, which this class of misconfiguration is specifically designed to evade.
These practices align with the identity governance and continuous-monitoring controls described in vendor security benchmarks for privileged access, which call for ongoing configuration review rather than point-in-time group membership checks.
Apply the safer control
Before you change production
Confirm the affected scope, export the current configuration, and test the replacement control in a non-production environment first.
Fix commands and configuration
AdminSDHolderCN=SystemadminCount=1Verify, roll back or escalate
Verify
Confirm both that the ACE is gone from AdminSDHolder and that it does not reappear on protected accounts after the next propagation cycle.Re-run the read-only ACL listing on AdminSDHolder and confirm the trustee no longer appears.Sample one protected account, ideally…
Rollback
If removing the ACE breaks a dependency that was not identified during diagnosis, restore the exact before-change ACL captured during correction rather than reconstructing it from memory.Reapply the access control entries recorded in the pre-change export to the AdminSDHolder object.Re-verify…
Escalate
Escalate when the blast radius is uncertain, the control cannot be tested safely, or remediation requires an outage or security exception.