adminCount "1" causing ACL Issues on Active Directory Objects.


The `adminCount` attribute in Active Directory is set to `1` when an account becomes a member of a "protected" group. These groups include high-privilege groups like:

  1. Domain Admns
  2. Enterprise Admins
  3. Schema Admins
  4. Administrators
  5. Account Operators
  6. Server Operators
  7. Backup Operators
  8. Print Operators

This means if you have an application as a user account that though nested groups ends up in one of these groups then you will get the adminCount value set to "1" not "0" that will then fire the AdminSDHolder process to run every 60 minutes.

These protected groups are managed by the AdminSDHolder process, which is responsible for applying special permissions to the objects in these groups to protect them from unintentional changes or attacks.

Overview of the AdminSDHolder Process

1. AdminSDHolder Object

This is a special object in AD from the "System" container that holds a template of the security descriptors that are applied to all protected groups and their members, this means if you have a permission that is required for protected users you will need to add this to that ACL.

2. AdminSDHolder Process

Every 60 minutes, a background process runs on the Primary Domain Controller (PDC) Emulator this then compares the security descriptors of members of the protected groups to the template in the AdminSDHolder object, the the ACL does not match then the permissions are reset to the ACL of AdminSDHolder, you can see this below:

Note : If you do not see the System then you need to ensure you choose View then Advanced Features from your MMC



If you then right click on this folder and choose Security - you will see the permissions applied to all objects that have adminCount set to 1 when the process runs, as below:


Issue : Inheritance being disabled

When `adminCount` is set to `1`, the object's ACL (Access Control List) is protected by disabling inheritance, this means that the object will no longer inherit permissions from its parent container

Careful Resetting Inheritance - its pointless

If you manually re-enable inheritance or remove the `adminCount` attribute from the object then the AdminSDHolder process will reset it during its next run, which will occur every 60 minutes.

Monitor in the Event Log

Event ID 4732/4733 :  These events will show when a user was added to or removed from a security-enabled global group, including protected groups.

Event ID 4662 : These events log modifications to objects, including changes to the `adminCount` attribute.

Updating the ACL on AdminSDHolder : Backup AdminSDHolder

If you are looking to ammend the ACL of the AdminSDHolder then you must remember that any changes you make to the AdminSDHolder ACL will be inherited by all accounts in protected groups the next time the process runs, if you are looking to ammend this back it up first:

$adminSDHolderACL = Get-ACL "AD:CN=AdminSDHolder,CN=System,DC=bear,DC=local"
$adminSDHolderACL | Export-Clixml -Path "AdminSDHolderACL.xml"

Once backed up, if you navigate to the folder adminSDHolder you can use the "Add" buttton to add required permissions to the holders of this role:


If you have a service account that writes data to objects, this service account will be unable to do this if it is not in this ACL list as it will have no permissions, however ensure you think about adding accounts to this ACL as this will apply to protected accounts in the domain.

Checking for Users in the state

If you wish to check for users in this state you can use this script below, obviously change the DN and the filtered users string to match you requirements.

Script : adminCountChecker.ps1

# Import the Active Directory module
Import-Module ActiveDirectory

# Define the distinguished name (DN) of the target OU
$ou = "OU=Employees,DC=bear,DC=local"

# Find all users with adminCount set to 1 within the specified OU
$adminUsers = Get-ADUser -Filter {adminCount -eq 1} -SearchBase $ou -Properties adminCount, Name

# Exclude users with "MngrBear" in their name (case insensitive)
$filteredUsers = $adminUsers | Where-Object { $_.Name -notmatch 'mngrbear' }

# Count the number of users found
$userCount = $filteredUsers.Count

# Output the count to the console
Write-Output "Number of users with adminCount = 1 in the specified OU (excluding 'deprovisioned'): $userCount"

# Output the list of users to the console
$filteredUsers | Select-Object Name, SamAccountName, adminCount

# Optionally, export the results to a CSV file
#$filteredUsers | Select-Object Name, SamAccountName, adminCount | Export-Csv -Path "adminCountUsers.csv" -NoTypeInformation

This will output all the users with adminCount set to "1" meaning they will all get the adminSDHolder permissions.

Users are not correct but do not have adminCount set to "1"

Well that can also make sense, if the data is wrong in your Active Directory this process only runs every 60 minutes, if they no longer qualify for the adminSDHolder role as for example they have been removed from the priviliged group (nested or not) the this "removal" has stopped the adminSDHolder permissions applying, but this does not reset the inhetitance status.

If you wish to check how many accounts have inheritance disabled, this script does not check for adminCount as this is not required for that anymore.

# Import the Active Directory module
Import-Module ActiveDirectory

# Define the distinguished name (DN) of the target OU
$ou = "OU=Departments,DC=bear,DC=local"

# Find all users in the specified OU
$allUsers = Get-ADUser -Filter * -SearchBase $ou -Properties Name, DistinguishedName

# Exclude users with "deprovisioned" in their name (case insensitive)
$filteredUsers = $allUsers | Where-Object { $_.Name -notmatch 'BearManaged' }

# Initialize a list to store users with inheritance disabled
$usersWithInheritanceDisabled = @()

foreach ($user in $filteredUsers) {
    try {
        # Get the ACL for the user
        $acl = Get-Acl -Path ("AD:\" + $user.DistinguishedName)

        # Check if inheritance is enabled
        $inheritanceEnabled = $acl.AreAccessRulesProtected -eq $false

        if (-not $inheritanceEnabled) {
            # Add to the list if inheritance is disabled
            $usersWithInheritanceDisabled += $user
        }
    } catch {
        Write-Warning "Failed to get ACL for user $($user.SamAccountName): $_"
    }
}

# Count the number of users with inheritance disabled
$userCount = $usersWithInheritanceDisabled.Count

# Output the count to the console
Write-Output "Number of users with inheritance disabled in the specified OU (excluding 'deprovisioned'): $userCount"

# Output the list of users to the console
$usersWithInheritanceDisabled | Select-Object Name, SamAccountName

# Optionally, export the results to a CSV file
#$usersWithInheritanceDisabled | Select-Object Name, SamAccountName | Export-Csv -Path "inheritanceDisabledUsers.csv" -NoTypeInformation

Previous Post Next Post

نموذج الاتصال