| name | analyzing-active-directory-acl-abuse |
| description | Detect dangerous ACL misconfigurations in Active Directory using ldap3 to identify GenericAll, WriteDACL, and WriteOwner abuse paths |
| domain | cybersecurity |
| subdomain | identity-security |
| tags | ["active-directory","acl-abuse","ldap","privilege-escalation"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
| nist_csf | ["PR.AA-01","PR.AA-05","PR.AA-06"] |
Analyzing Active Directory ACL Abuse
Overview
Active Directory Access Control Lists (ACLs) define permissions on AD objects through Discretionary Access Control Lists (DACLs) containing Access Control Entries (ACEs). Misconfigured ACEs can grant non-privileged users dangerous permissions such as GenericAll (full control), WriteDACL (modify permissions), WriteOwner (take ownership), and GenericWrite (modify attributes) on sensitive objects like Domain Admins groups, domain controllers, or GPOs.
This skill uses the ldap3 Python library to connect to a Domain Controller, query objects with their nTSecurityDescriptor attribute, parse the binary security descriptor into SDDL (Security Descriptor Definition Language) format, and identify ACEs that grant dangerous permissions to non-administrative principals. These misconfigurations are the basis for ACL-based attack paths discovered by tools like BloodHound.
When to Use
- When investigating security incidents that require analyzing active directory acl abuse
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
Detection Gaps & Validation
- Edges BloodHound under-collects: default
SharpHound collection misses ACEs on ADCS objects (Enroll/WriteProperty on certificate templates → ESC1-ESC7), GPO-linked OUs, and gMSA/msDS-ManagedPassword read rights. Run Get-DomainObjectAcl -ResolveGUIDs (PowerView) and compare ACE counts against the BloodHound graph.
- Extended-rights blind spots: access masks like
ADS_RIGHT_DS_CONTROL_ACCESS (0x100) gate User-Force-Change-Password and DS-Replication-Get-Changes-All (DCSync). A GenericAll filter that only checks 0x10000000 misses these GUID-scoped ACEs — match the ObjectType GUID, not just the mask.
- Inherited vs explicit: abusable ACEs are often inherited from a parent OU; tooling that only reads
IsInherited=False ACEs misses them. Walk the inheritance chain and flag INHERITED_ACE entries too.
- Deny ACE ordering: a permissive Allow after a Deny still loses, but canonicalization bugs and shadow-credentials (
msDS-KeyCredentialLink WriteProperty) bypass intent — validate with Test-ADCanonicalAcl.
- How to confirm a hit: prove the path, don't just report the ACE. For on a user, confirm a password reset or shadow-credential add in a lab; for on a group, add an ACE then self to the group and verify token group membership with . Cross-check the SID is not a tier-0 principal before flagging.