In Active Directory environments, the adminSDHolder object plays a crucial role in protecting privileged accounts. Every hour, the SDProp process runs and applies the ACL of adminSDHolder to all accounts with adminCount attribute set to 1 (or greater than 0). This can sometimes cause unexpected permission changes for administrative accounts.
Finding accounts with adminCount > 0 is important for:
- Security audits and compliance checks
- Troubleshooting permission issues
- Identifying accounts that might be protected by adminSDHolder
- Documenting privileged access in your environment
Here's a comprehensive PowerShell script that queries Active Directory for users with adminCount > 0:
# Import the Active Directory module
Import-Module ActiveDirectory
# Search for all users with adminCount > 0
$adminUsers = Get-ADUser -Filter {adminCount -gt 0} -Properties adminCount, DistinguishedName, LastLogonDate, Enabled
# Output the results
$adminUsers | Select-Object Name, SamAccountName, DistinguishedName, adminCount, Enabled, LastLogonDate |
Sort-Object adminCount -Descending |
Format-Table -AutoSize
# Optional: Export to CSV
$adminUsers | Export-Csv -Path "C:\Temp\AdminUsers.csv" -NoTypeInformation
For more comprehensive reporting, use this enhanced script:
# Enhanced AD Admin Users Report
$report = @()
$adminUsers = Get-ADUser -Filter {adminCount -gt 0} -Properties *
foreach ($user in $adminUsers) {
$report += [PSCustomObject]@{
Name = $user.Name
Username = $user.SamAccountName
DN = $user.DistinguishedName
adminCount = $user.adminCount
Enabled = $user.Enabled
LastLogon = $user.LastLogonDate
PasswordLastSet = $user.PasswordLastSet
MemberOf = ($user.MemberOf | Get-ADGroup | Select-Object -ExpandProperty Name) -join ", "
ProtectedByAdminSDHolder = ($user.adminCount -gt 0)
}
}
# Display and export results
$report | Sort-Object adminCount -Descending | Format-Table -AutoSize
$report | Export-Csv -Path "C:\Temp\AdminUsers_Detailed.csv" -NoTypeInformation
For domains with many users, add server and page size parameters:
Get-ADUser -Filter {adminCount -gt 0} -Properties adminCount -Server "YourDomainController" -ResultPageSize 1000
Create a scheduled task to run this weekly and email the results:
# PowerShell script to email admin user report
$report = Get-ADUser -Filter {adminCount -gt 0} -Properties * | Select-Object Name, SamAccountName, adminCount, Enabled, LastLogonDate
$emailParams = @{
From = "ADMonitor@yourdomain.com"
To = "security-team@yourdomain.com"
Subject = "Weekly AD Admin Users Report"
Body = $report | ConvertTo-Html | Out-String
SmtpServer = "your.smtp.server"
}
Send-MailMessage @emailParams -BodyAsHtml
- The adminCount attribute is automatically set when adding users to protected groups
- Manually setting adminCount to 0 won't stop SDProp from resetting it
- Consider reviewing these accounts regularly as part of your security practices
When managing Active Directory security, the adminSDHolder object quietly impacts privileged accounts by resetting their ACLs every hour. The key indicator is the adminCount attribute being set to 1, which triggers this protection mechanism.
Many organizations unknowingly have service accounts or delegated admins affected by AdminSDHolder. These accounts suddenly lose permissions when their ACLs get reset. Finding them proactively prevents support tickets.
# Find all users with adminCount > 0
Get-ADUser -Filter {adminCount -gt 0} -Properties adminCount,MemberOf,LastLogonDate |
Select-Object Name,SamAccountName,DistinguishedName,adminCount,
@{Name='Groups';Expression={$_.MemberOf -join ";"}},
@{Name='LastLogonDays';Expression={[math]::Round((New-TimeSpan -Start $_.LastLogonDate -End (Get-Date)).TotalDays,0)}} |
Export-Csv -Path "ProtectedUsers.csv" -NoTypeInformation
# Search specific OUs with error handling
try {
$SearchBase = "OU=Admins,DC=domain,DC=com"
$Results = Get-ADUser -SearchBase $SearchBase -Filter {adminCount -gt 0}
-Properties * -ErrorAction Stop |
Select-Object Name,SamAccountName,UserPrincipalName,Enabled,
@{Name='ProtectionStatus';Expression={
if($_.adminCount -gt 0){"Protected"}else{"Normal"}
}}
$Results | Format-Table -AutoSize
$Results | Export-Csv -Path "AdminSDHolder_Users_Report.csv" -NoTypeInformation
}
catch {
Write-Warning "AD Query Failed: $_"
}
The script outputs several key data points:
- adminCount=1: Currently protected by AdminSDHolder
- Groups: Shows nested group memberships that might have triggered protection
- LastLogonDays: Helps identify stale privileged accounts
Create a scheduled task that runs weekly and emails the report:
# Email report automation
$Body = Get-Content "ProtectedUsers.csv" | Out-String
Send-MailMessage -From "admon@domain.com" -To "itsecurity@domain.com"
-Subject "Weekly AdminSDHolder Report" -Body $Body -SmtpServer "mail.domain.com"