Access Control List (ACL) Abuse Primer
ACLs control who can access which AD objects and at what level. Misconfigurations leak permissions to principals that don’t need them, enabling lateral movement, privilege escalation, and persistence. ACL issues are invisible to vulnerability scanners and often go unchecked for years.
ACL Fundamentals
An Access Control List (ACL) defines which security principals (users, groups, processes) can access an object and what rights they have. The individual entries in an ACL are Access Control Entries (ACEs). Every AD object has an ACL, and each ACL can contain multiple ACEs.
Two Types of ACLs
| Type | Purpose |
|---|---|
| DACL (Discretionary Access Control List) | Defines which principals are granted or denied access to an object. Made up of allow/deny ACEs. |
| SACL (System Access Control List) | Logs access attempts to secured objects for auditing. |
DACL behavior:
- No DACL exists → all access granted (full rights to everyone)
- DACL exists but has no ACEs → all access denied
- DACLs are evaluated top-to-bottom; processing stops when an access denied ACE is matched
ACE Components
Each ACE contains four parts:
- SID — security identifier of the user/group with access
- Type flag — access denied, access allowed, or system audit
- Inheritance flags — whether child objects inherit this ACE
- Access mask — 32-bit value defining the specific rights granted
Three ACE Types
| ACE Type | Location | Purpose |
|---|---|---|
| Access denied | DACL | Explicitly denies access to a principal |
| Access allowed | DACL | Explicitly grants access to a principal |
| System audit | SACL | Generates audit logs on access attempts |
Abusable ACE Permissions
These permissions can be enumerated with BloodHound and exploited with PowerView (Windows) or Impacket/bloodyAD (Linux).
| Permission | Effect | Abuse Tool (PowerView) |
|---|---|---|
| ForceChangePassword | Reset a user’s password without knowing the current one | Set-DomainUserPassword |
| GenericAll | Full control over the target object | Set-DomainUserPassword, Add-DomainGroupMember, read LAPS password |
| GenericWrite | Write to any non-protected attribute on the object | Set-DomainObject (assign SPN for Kerberoasting, modify group membership) |
| WriteOwner | Change the owner of the object | Set-DomainObjectOwner |
| WriteDACL | Modify the DACL (grant yourself or others new permissions) | Add-DomainObjectACL |
| AllExtendedRights | Perform all extended operations (password reset, group changes) | Set-DomainUserPassword, Add-DomainGroupMember |
| AddSelf | Add yourself to a security group | Add-DomainGroupMember |
| Add Members | Add any principal to a group | Add-DomainGroupMember |
Key Permissions in Detail
ForceChangePassword — Reset a user’s password without knowing the current one. Use cautiously and get client approval before resetting passwords on an engagement.
GenericWrite — Write to non-protected attributes. Over a user: assign an SPN and Kerberoast them (targeted Kerberoasting). Over a group: add yourself or another principal. Over a computer: perform resource-based constrained delegation.
GenericAll — Full control. Over a user: change password or Kerberoast. Over a group: modify membership. Over a computer with LAPS: read the local admin password.
WriteDACL — Modify the DACL itself. Grant yourself GenericAll, then abuse from there. Powerful for establishing persistence.
WriteOwner — Take ownership of the object, then modify its DACL to grant yourself full control.
Attack Scenarios
| Scenario | Description |
|---|---|
| Abusing password reset permissions | Help Desk / IT accounts often have ForceChangePassword on privileged accounts. Take over such an account and reset a higher-privilege user’s password. |
| Abusing group membership management | Staff with Add Members rights on privileged groups. Add a controlled account to Domain Admins or other sensitive groups. |
| Excessive user rights | Software installs (Exchange is notorious) or legacy configs grant unintended rights. Users may have GenericAll or WriteDACL on high-value objects without anyone knowing. |
Enumeration
BloodHound
Import domain data via SharpHound (Windows) or bloodhound-python (Linux). BloodHound visualizes ACL attack paths and highlights edges like:
- ForceChangePassword
- GenericAll / GenericWrite
- WriteDACL / WriteOwner
- AllExtendedRights
- AddSelf / AddMember
- ReadGMSAPassword
PowerView
Import-Module .\PowerView.ps1
# Find interesting ACLs for a specific user
Find-InterestingDomainAcl -ResolveGUIDs | ?{$_.IdentityReferenceName -match "TARGET_USER"}
# Get ACL for a specific object
Get-DomainObjectAcl -Identity "TARGET" -ResolveGUIDs
# Find all objects where a user has GenericAll
Get-DomainObjectAcl -ResolveGUIDs | ?{$_.ActiveDirectoryRights -match "GenericAll" -and $_.SecurityIdentifier -match "USER_SID"}
Other Edges to Watch For
- ReadGMSAPassword — read the password of a Group Managed Service Account (use
GMSAPasswordReaderor similar) - Unexpire-Password / Reanimate-Tombstones — less common extended rights; research exploitation on a case-by-case basis
Operational Notes
- ACL attacks can be destructive (password resets, group membership changes). Get client approval before executing and document everything.
- Always revert changes after the attack: remove group memberships, restore original owners/DACLs.
- Include all changes in the report with clear documentation showing changes were reverted.
- ACL abuse is especially valuable when the client has addressed all “low hanging fruit” — these paths often survive standard hardening.