PRACTITIONER GUIDE | ACTIVE DIRECTORY SECURITY
Practitioner GuideUpdated 12 min read

Active Directory Delegation Model Audit: How to Find Non-Standard Permissions That Grant Unexpected Control Over AD Objects

WriteDACL
permission on a user object effectively grants full control -- a holder of WriteDACL can grant themselves or any other account any permission on the object
GenericWrite
on a user object allows modifying the servicePrincipalName attribute (Kerberoastable by the attacker) and adding scriptPath or other attributes that affect logon
5 high-risk
AD delegation rights that consistently create escalation paths: WriteDACL, GenericWrite, GenericAll, WriteProperty (member), AllExtendedRights
Inheritance
ACEs on OUs propagate to all child objects by default -- a single permissive ACE on a high-level OU can grant unexpected control over hundreds of accounts

SponsoredRetool

Retool's new app builder is where AI-generated code ships safely

Building apps with AI is easy. Getting them to production safely is another story.

Start building for free today

Active Directory delegations accumulate silently. A helpdesk team gets ResetPassword delegation on the entire Users OU in 2015 for a password self-service project. The project ends but the delegation remains. In 2020, the helpdesk role is consolidated and the old security group is no longer actively managed -- but it still has membership and still has the delegation. In 2024, a former helpdesk member whose account was never disabled uses that delegation to reset a target user's password. The audit process exposes these paths before attackers discover them.

High-Risk Delegation Rights and What They Enable

Not all delegated rights create equal risk. These are the most dangerous:

GenericAll / Full Control: Grants every possible permission on the object. Equivalent to Domain Admin for the specific object. Allows password reset, group membership modification, disabling the account, and modifying group memberships.

WriteDACL: Allows modifying the object's DACL. An attacker holding WriteDACL can grant themselves GenericAll on the object, effectively a privilege escalation step. This right alone is sufficient for complete object compromise.

WriteOwner: Allows changing the object's owner. Owners have implicit permission to modify the DACL. WriteDACL and WriteOwner are functionally equivalent paths to object control.

GenericWrite: Allows writing any non-protected attribute. On user objects: can modify servicePrincipalName (enabling targeted Kerberoasting), scriptPath (adds malicious script to run at logon), homeDirectory, and other attributes.

AllExtendedRights: Grants all extended rights on the object. On user objects, this includes the User-Force-Change-Password extended right (force password reset without knowing current password).

WriteProperty (Member): On group objects, allows adding or removing group members. A holder of this right on Domain Admins can add themselves to the group.

ResetPassword / User-Force-Change-Password: Allows resetting the account's password without knowing the current password. Dangerous for delegations scoped to privileged user OUs.

Auditing OU-Level Delegations with PowerShell

The AD PowerShell module provides Get-ACL for AD objects, but reading AD ACLs requires the AD provider:

# Import AD provider for ACL access
Import-Module ActiveDirectory

# Audit delegations on a specific OU and all child OUs
function Get-ADOUDelegations {
    param([string]$OUPath)
    
    $ous = Get-ADOrganizationalUnit -Filter * -SearchBase $OUPath -SearchScope Subtree
    
    foreach ($ou in $ous) {
        $acl = Get-Acl -Path "AD:\$($ou.DistinguishedName)"
        
        foreach ($ace in $acl.Access) {
            # Skip built-in high-privilege accounts that are expected
            if ($ace.IdentityReference -notmatch "BUILTIN\\|NT AUTHORITY\\|S-1-5-18|S-1-5-32") {
                # Flag high-risk rights
                $isHighRisk = $false
                $highRiskRights = @("GenericAll","GenericWrite","WriteDacl","WriteOwner","AllExtendedRights")
                foreach ($right in $highRiskRights) {
                    if ($ace.ActiveDirectoryRights -match $right) { $isHighRisk = $true }
                }
                
                if ($isHighRisk -or $ace.ActiveDirectoryRights -match "WriteProperty") {
                    [PSCustomObject]@{
                        OU = $ou.DistinguishedName
                        Identity = $ace.IdentityReference
                        Rights = $ace.ActiveDirectoryRights
                        InheritanceType = $ace.InheritanceType
                        ObjectType = $ace.ObjectType
                        IsInherited = $ace.IsInherited
                        AccessControlType = $ace.AccessControlType
                    }
                }
            }
        }
    }
}

# Run against your user and admin OUs
Get-ADOUDelegations -OUPath "OU=Users,DC=domain,DC=com" | 
    Where-Object {-not $_.IsInherited} |  # Focus on explicitly set ACEs first
    Sort-Object OU, Identity | 
    Export-Csv ou-delegations.csv -NoTypeInformation

The IsInherited = $false filter surfaces explicit delegations -- these are the ones that were deliberately granted and are the most likely to be non-standard.

Free daily briefing

Briefings like this, every morning before 9am.

Threat intel, active CVEs, and campaign alerts, distilled for practitioners. 50,000+ subscribers. No noise.

Identifying Who Has Delegation Over Privileged User OUs

The highest-priority delegation audit is over the OUs containing Tier 0 and Tier 1 admin accounts:

# Identify all non-admin accounts with any write permissions on admin user OUs
$adminOUs = @(
    "OU=Tier0Admins,OU=AdminAccounts,DC=domain,DC=com",
    "OU=Tier1Admins,OU=AdminAccounts,DC=domain,DC=com"
)

$expectedIdentities = @(
    "BUILTIN\Administrators",
    "NT AUTHORITY\SYSTEM",
    "NT AUTHORITY\ENTERPRISE DOMAIN CONTROLLERS",
    "DOMAIN\Domain Admins",
    "DOMAIN\Enterprise Admins",
    "Creator Owner"
)

foreach ($ouDN in $adminOUs) {
    $acl = Get-Acl -Path "AD:\$ouDN"
    $unexpectedACEs = $acl.Access | Where-Object {
        ($expectedIdentities -notcontains $_.IdentityReference.ToString()) -and
        ($_.AccessControlType -eq "Allow")
    }
    
    if ($unexpectedACEs) {
        Write-Output "[!] Non-standard ACEs on $ouDN:"
        $unexpectedACEs | Format-Table IdentityReference, ActiveDirectoryRights, InheritanceType
    }
}

For each unexpected ACE found:

  1. Identify the current members of the identity (Get-ADGroupMember if it is a group)
  2. Determine when the delegation was added and by whom (review AD audit events for the target OU using Event ID 5136 in Security log)
  3. Verify whether the delegation is still operationally required
  4. Remove if not required: Set-Acl -Path "AD:\$ouDN" -AclObject $modifiedACL

Automated Discovery with BloodHound

BloodHound automates delegation discovery across the entire domain by collecting ACLs on all objects and computing attack paths to Domain Admin:

Using BloodHound CE (Community Edition) for delegation audit:

# Collect AD data with SharpHound collector
.\SharpHound.exe --CollectionMethods ACL,Group,ObjectProps,Trusts --OutputDirectory C:\temp\bh-output

BloodHound queries for delegation-based attack paths:

// Find all principals with GenericWrite on any admin user
MATCH (n)-[:GenericWrite]->(m:User)
WHERE m.admincount = true
RETURN n.name, m.name, labels(n)

// Find all principals with WriteDACL on privileged objects
MATCH (n)-[:WriteDacl]->(m)
WHERE m.admincount = true OR m.objectid CONTAINS 'Domain Admins'
RETURN n.name, m.name, labels(n)

// Shortest path from a specific low-privilege account to Domain Admin
MATCH p=shortestPath((s:User {name:'user@domain.com'})-[*1..]->(t:Group {name:'DOMAIN ADMINS@DOMAIN.COM'}))
RETURN p

BloodHound is more comprehensive than manual ACL review for finding multi-hop paths (user A has WriteDACL on group B, group B has GenericWrite on user C who is in Domain Admins), but manual ACL review is faster for targeted audits of specific OUs.

Remediating Non-Standard Delegations

After identifying non-standard delegations, remediation follows this sequence:

Step 1: Verify the delegation is not operationally active Check whether the delegated identity is still used. If a service account had delegation, verify the service still exists. Check the last login date for any users in a delegated group.

Step 2: Remove the ACE with PowerShell

# Remove a specific ACE from an OU
$ouDN = "OU=Users,DC=domain,DC=com"
$targetIdentity = "DOMAIN\old-helpdesk-group"

$path = "AD:\$ouDN"
$acl = Get-Acl $path

# Filter out the specific ACE to remove
$aceToRemove = $acl.Access | Where-Object {
    $_.IdentityReference.ToString() -eq $targetIdentity
}

foreach ($ace in $aceToRemove) {
    $acl.RemoveAccessRule($ace) | Out-Null
}

Set-Acl -Path $path -AclObject $acl
Write-Output "Removed $($aceToRemove.Count) ACE(s) for $targetIdentity on $ouDN"

Step 3: Verify with BloodHound re-collection Re-collect AD data with SharpHound after remediation and re-run the attack path queries to confirm the path is gone.

Step 4: Establish a delegation register Document all intended delegations in a configuration management database or a simple CSV that is reviewed annually. Include: OU path, delegated identity, rights granted, business justification, approval ticket, and review date. Any delegation not in the register is a finding.

The bottom line

AD delegation audits consistently surface privilege escalation paths that standard group membership reviews miss. WriteDACL, GenericWrite, and ResetPassword on privileged user OUs are the highest-priority findings. Use the PowerShell ACL audit for targeted OU reviews and BloodHound for comprehensive multi-hop path analysis. Establish a delegation register so any future ACE that is not documented is immediately identifiable as non-standard.

Frequently asked questions

How often should AD delegation audits be run?

For Tier 0 and Tier 1 admin OUs, run a delegation audit quarterly. For the full domain, annually is typically sufficient unless you have a high-change-rate environment. More importantly, configure AD audit logging to alert on ACE changes (Event ID 5136 -- A directory service object was modified) for sensitive OUs in real time. The quarterly audit catches accumulated drift; real-time alerting catches active manipulation.

Does removing a delegation break any Group Policy application?

GPO application uses Kerberos authentication and does not rely on delegated LDAP permissions on user objects. Removing delegated permissions does not affect GPO processing. The only scenario where ACE removal could affect Group Policy is if you remove read access for Authenticated Users on the OU itself, which would prevent standard clients from reading GPO links. Standard delegation remediation (removing over-permissive write rights) does not affect GPO processing.

What is the AdminSDHolder and how does it relate to delegation audits?

AdminSDHolder is an AD container whose ACL is periodically copied to all protected accounts (Domain Admins, Schema Admins, etc.) by the SDProp process, which runs every 60 minutes by default. This means any delegation you set on a protected account's object will be overwritten within 60 minutes by the AdminSDHolder ACL. Conversely, if someone modifies the AdminSDHolder ACL itself, those modified permissions will propagate to all protected accounts within 60 minutes. The AdminSDHolder object's ACL is a critical audit target -- run `Get-Acl 'AD:\CN=AdminSDHolder,CN=System,DC=domain,DC=com'` and compare against a known-good baseline.

How do I find all accounts that can reset passwords on user objects in a specific OU?

Run: `$acl = Get-Acl 'AD:\OU=Users,DC=domain,DC=com'; $acl.Access | Where-Object { $_.ActiveDirectoryRights -match 'ExtendedRight' -and ($_.ObjectType -eq '00299570-246d-11d0-a768-00aa006e0529' -or $_.ObjectType -eq '00000000-0000-0000-0000-000000000000') }`. The GUID `00299570-246d-11d0-a768-00aa006e0529` is the ObjectType GUID for the User-Force-Change-Password extended right. The all-zeros GUID means the ACE applies to all extended rights. Both GUIDs, combined with InheritanceType that includes descendant User objects, indicate password reset delegation.

How do I baseline and compare AD ACL changes over time to detect delegation abuse?

Export ACL snapshots using `Get-ADObject -SearchBase 'DC=domain,DC=com' -SearchScope Subtree -LDAPFilter '(objectClass=*)' -Properties nTSecurityDescriptor | Export-Clixml -Path acl-snapshot-$(Get-Date -Format yyyyMMdd).xml` on a schedule (weekly). Compare snapshots with `Compare-Object` on the nTSecurityDescriptor property to surface new ACEs. For continuous monitoring, enable DS Access auditing (Audit Directory Service Changes) and alert on Event ID 5136 (Directory Service Object Modified), which logs the specific attribute modified and the old and new values. SDProp changes (originating from the SYSTEM account) are expected and can be filtered; all other ACE modifications on high-value objects warrant investigation.

What is AdminSDHolder and how does it affect Active Directory delegation?

AdminSDHolder is an AD object (CN=AdminSDHolder,CN=System,DC=domain,DC=com) whose ACL serves as the template for ACLs on protected accounts (members of privileged groups like Domain Admins, Enterprise Admins, Schema Admins). Every 60 minutes, the SDProp background process compares the ACL of each protected account against the AdminSDHolder template and resets any differences. This means custom delegation ACEs added to Domain Admin accounts are silently removed every hour. If you need to delegate permissions on protected accounts (for example, allowing a helpdesk group to reset a specific protected user's password), add the permission to the AdminSDHolder object itself rather than the user object. Be aware that the AdminSDHolder ACL is a high-value target: unauthorized modifications to it grant persistent permissions on all protected accounts.

Sources & references

  1. Microsoft: Best practices for securing Active Directory
  2. SpecterOps: BloodHound CE Documentation

Free resources

25
Free download

Critical CVE Reference Card 2025–2026

25 actively exploited vulnerabilities with CVSS scores, exploit status, and patch availability. Print it, pin it, share it with your SOC team.

No spam. Unsubscribe anytime.

Free download

Ransomware Incident Response Playbook

Step-by-step 24-hour IR checklist covering detection, containment, eradication, and recovery. Built for SOC teams, IR leads, and CISOs.

No spam. Unsubscribe anytime.

Free newsletter

Get threat intel before your inbox does.

50,000+ security professionals read Decryption Digest for early warnings on zero-days, ransomware, and nation-state campaigns. Free, daily, no spam.

Unsubscribe anytime. We never sell your data.

Eric Bang
Author

Founder & Cybersecurity Evangelist, Decryption Digest

Cybersecurity professional with expertise in threat intelligence, vulnerability research, and enterprise security. Covers zero-days, ransomware, and nation-state operations for 50,000+ security professionals every morning.

Black Hat Giveaway

Win a $2,495 Black Hat pass.

Full-access to Black Hat USA 2026 in Las Vegas. Subscribe free to enter.

Joins Decryption Digest daily briefing. Unsubscribe anytime.

Giveaway: Black Hat USA 2026 Full-Access Pass ($2,495 value)

Details →
Daily Briefing

Subscribe to enter the giveaway

Every subscriber is automatically entered. You also get daily threat intel every morning: zero-days, ransomware, and nation-state campaigns. Free. No spam.

Already subscribed? You're already entered.

Giveaway

Win a $2,495 Black Hat USA 2026 pass.