Cleaning up AdminSDHolder orphans

By | September 11, 2013

I quite regularly come across Active Directory environments where users have been mistakenly added to groups protected by the AdminSDHolder and subsequently removed when the mistake has been realised.  This process creates “orphans” because the AdminSDHolder process doesn’t tidy up after itself.  Here’s what happens:

  1. User added to group protected by the AdminSDHolder (e.g. Account Operators)
  2. The AdminSDHolder process (actually a thread within LSASS.EXE on the PDC Emulator) sets the adminCount attribute value to 1 on the user object and replaces the user’s security descriptor with that of the AdminSDHolder container object.
  3. User is then removed from Account Operators.
  4. The adminCount value of 1 is not cleared and the security descriptor is not changed (i.e. remains the same as that of the AdminSDHolder).

It doesn’t make sense to leave these orphans as they are.  For one, it plays havoc with any delegation model that is in place.  It also makes it difficult to determine what objects are actually protected.  For example, searching for objects that have an adminCount of 1 will potentially give you misleading results.

So what can you do about it?  One option is to manually look at each object to determine whether it is genuinely a protected object and then clear the adminCount value and re-set the inheritance flag for any objects no longer protected.  This is likely to be incredibly time consuming as you will need to factor in nested group membership into your investigation.  Another option is to run a script that clears the adminCount value and resets the inheritance flag for *all* protected objects.  Any objects that should genuinely be protected will be re-protected (I just made that word up) when the AdminSDHolder next cycles (within 1 hour by default).

The second option sounds like the clear winner.  There are some small risks that you should be aware of with this approach.  Firstly, there might be some malware “lurking” in your environment that will take the opportunity to compromise privileged accounts when they are in an unprotected state (even for a short period).  Secondly, re-setting the inheritance flag on objects might cause unforeseen problems.  For example, a user object might have had the inheritance flag unchecked prior to being protected by the AdminSDHolder.

Basically, there is no silver bullet here.  Personally, I think the small risk associated with the scripted option generally outweighs the negative impact of AdminSDHolder orphans.  Here’s the script that I use:

#########################################################
#
# Name: Cleanup-AdminSDHolder.ps1
# Author: Tony Murray
# Version: 1.0
# Date: 28/08/2013
# Comment: PowerShell 2.0 script to re-set inheritance
# flag for objects no longer protected by the 
# AdminSDHolder
#
########################################################### 

# Import the AD module
Import-Module ActiveDirectory

# Find objects that appear to be protected in AD
$probjs = Get-ADObject -LDAPFilter "(admincount=1)"
$bcount = $probjs.count
if ($bcount) {
    write-host "Protected object count before change is $bcount"
} # end if
else {
    write-host "No objects are currently protected - nothing to do"
    exit
} # end else

# Change to the AD drive
cd AD:

# Loop through protected objets to set inheritance flag
# and clear the adminCount value
foreach ($probj in $probjs) {
    $dn = $probj.distinguishedname
    $acl = get-acl $dn
    if ($acl.AreAccessRulesProtected) {
        write-host "$dn has inheritance blocked - we will remove the block"
        $acl.SetAccessRuleProtection($false, $false);
        set-acl -aclobject $acl $dn
        # We need to clear the adminCount attribute too
        Set-ADObject -Identity $dn -Clear adminCount
    } # end if
} # end foreach    

# Count the number of protected objects
$acount = (Get-ADObject -LDAPFilter "(admincount=1)").count
if ($acount) {
    write-host "Protected object count after change is $acount"
} # end if
else {
    write-host "No objects are currently protected"
} # end else

Please leave a comment if you have any thoughts on how to improve the script, or if you are aware of a better method of handling AdminSDHolder orphans.

You can download a copy of the script here: Cleanup-AdminSDHolder

 

3 thoughts on “Cleaning up AdminSDHolder orphans

  1. Pingback: Script to Create an Overview and Full Report of all Group Objects in a Domain

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.