TL;DR
Megan Nilsen and Andrew Schwartz of TrustedSec published a series of great blog posts dealing with detecting AD attacks using Windows audit logs. In their setup, they created a GPO to enable extra Windows log events, performed SACL configuration, and used Splunk to ingest the logs and write custom detection queries.
In this article, we wanted to see if we could build upon their research and move from detection toward prevention, using just the LDAP Firewall. Our goal is to eliminate the setup complexity and provide a solution that stops DACL-based attacks before they happen, instead of alerting on them after the fact.
We also encourage you to read our Leash the Hounds blog post, where we covered how to block the LDAP-based reconnaissance performed by the different BloodHound variants. Combining the approaches from that article with the configuration presented below will yield a tight LDAP security posture.
Background
In Windows, Discretionary Access Control Lists (DACL) are used to specify the principles (e.g. users, groups) that are allowed or denied access to an object. As AD environments keep changing (entities are added, permissions are modified, etc.), and because they are difficult to audit and control, DACLs often become stagnant and misconfigured.
Attackers often take advantage of this fact to perform lateral movement and/or privilege escalation. This is done as stealthy reconnaissance (for example, understanding which user is allowed to add members to a sensitive group), or more proactively (such as adding Key Credentials during a Shadow Credentials attack). DACLs are used in attacks such as DCSync, Kerberoasting, and Evil GPOs, and some commonly used tools that exploit them include BloodHound, PowerSploit, Powermad, and Impacket modules.
For more information about DACL-based attacks, check out the DACL Abuse article (and the mind map in particular) created by The Hacker Recipes.
What DACL Attacks Have in Common
Going over online resources about DACL attacks, we found that most of the attacks were based on performing LDAP requests for one of the following purposes:
-
Searching the entire schema and reading AD object attributes that contain sensitive information
-
Modifying an attribute of an existing AD object
Some examples of these include modifying the KeyCredentialLink attribute during a Shadow Credentials attack or sAMAccountName in a sAMAccountName spoofing attack, and reading LAPS passwords which are stored in the ms-MCS-AdmPwd attribute. We will not go over all the different attributes in detail (as Megan and Andrew already covered these in length for their blog posts), but instead, we will focus on how to configure the LDAP Firewall to detect and block any requests that attempt to make these changes illegitimately.
Protecting Against DACL Attacks with the LDAP Firewall
Our approach to blocking DACL-based attacks includes 3 main steps. First, we need to compile a list of the sensitive attributes used in attacks. Then, we set up an audit configuration to log suspicious LDAP requests, which allows us to better understand our environment. Once we figure out which of the logged LDAP requests are legitimate, we can move on to an active prevention configuration, making sure to add rules that allow legitimate sources to continue functioning correctly.
At the end of the article, we will also run some LDAP-based attack tools and demonstrate that our configuration is successful in blocking them.
Step 1 – Researching DACL Attacks
Our first step was to go over the attacks listed in the previously mentioned articles and create a mapping of each operation type and the attributes that are used with each one. TrustedSec’s articles were a useful starting point, as they have already done much of this work for us. For example, if we look at section 5.5 of their first article, they explain that this attack changes the path to a logon script (allowing for remote code execution) by modifying the scriptPath LDAP attribute. We will use this information later to add an LDAP Firewall rule that blocks remote modifications of this attribute.
For other DACL attack techniques, where clear documentation like this was not available, we needed to research further. This could be done either by reading the source code of the attack tools to find out which attributes are used or by manually running the tool in a lab with LDAP Firewall installed to see what queries were being generated. Let’s look at some examples of analyzing these attacks.
Reading the Source Code - GPO Abuse
A GPO Abuse attack allows for remote code execution by creating an immediate scheduled task that runs on remote hosts instantly. WithSecure Labs has a blog post that includes some details on how the SharpGPOAbuse tool works, but in this case, it was easier to follow the source code of the Python implementation of the tool (pyGPOAbuse). Here we can see the two attributes that are being modified (gPCUserExtensionNames and gPCMachineExtensionNames), which we can add to our list of Modify attributes to block.
LDAP attributes used in GPO Abuse attacks (pyGPOAbuse source code)
LDAP Firewall Auditing
For this stage, it is also useful to put the LDAP Firewall in full audit mode on a lab DC. This allows us to run the attacks in a lab environment and check the LDAPFW Event Logs to see what the queries look like. To achieve this, the following configuration can be used:
Note: the
As this configuration might generate a lot of events (especially search requests), it is only recommended for use in a lab environment. The first rule ignores local queries, as they are common and are less relevant to our purpose, and the second rule allows and audits all other operations.
Once we have this configuration running on our test DC, we can run some attacks and view the queries being generated in our Event Log. In this case, we used Powermad’s Set-MachineAccountAttribute to change the machine’s msDS-AllowedToDelegateTo attribute.
Going to the Event Logs in our lab DC, we can see that running this command generated a Modify operation, with the DN set to our target host (pc01) and the entry list containing our specified value (dc01$) for the attribute.
Step 2 – Auditing Suspicious Operations
Now that we have our mapping of LDAP operations and sensitive attributes, we can create an LDAP Firewall configuration that audits all LDAP requests we suspect to be DACL-based attacks. This configuration can be used in production environments to see if any of the LDAP operations we intend to block are used legitimately in our environment.
Here is the example config on our Git repository.
This configuration will audit suspicious LDAP operations in the Windows Event Log (without blocking the requests), which we can later use to build a list of allowed sources (IPs, users, or groups) that perform these operations legitimately. If we break down the configuration, it works like this:
-
If the incoming LDAP request is a local operation, allow the operation and don’t audit it
-
Else, if the incoming LDAP request is a Search operation with a subtree scope (iterative search) that attempts to read a sensitive attribute, audit and allow it
a. Attacks using this technique include BloodHound (reading attributes such as msDS-AllowedToDelegateTo and admincount) and LAPSDumper (reading LAPS passwords from the ms-Mcs-AdmPwd attribute) -
Else, if the incoming LDAP request is a Modify operation that attempts to write to one of the known sensitive attributes, audit and allow it
a. Attacks using this technique include Shadow Credentials (modifying the msDS-KeyCredentialLink attribute) and GPO Abuse (modifying the gPCMachineExtensionNames and gPCUserExtensionNames attributes) -
Else, allow the operation without auditing it
Step 3 – DACL Attack Prevention
Once we finish our auditing period, we can change our configuration to block and audit any suspicious LDAP operations, while still allowing approved sources to manage the AD infrastructure. Any legitimate source we discovered in the baselining period can be added to the first rule, which will allow it to continue querying the DC without restrictions. Of course, a more granular approach could be employed by adding more specific rules, such as only allowing a source to do a specific operation with specific parameters. The configuration we used for our environment is available on our Git repository.
This configuration works as follows:
-
Allow any LDAP operations performed locally. Approved sources (such as IPs of any infrastructure management servers used to administer AD, or specific users and/or groups) can be added to this rule.
-
Else, block any Search requests that attempt to iteratively read sensitive attributes
-
Else, block any Modify requests that attempt to edit the sensitive attributes
-
Else, allow any Search requests but do not audit them (these generate a lot of noise)
-
Else, allow and audit the request
Attacks Prevention Demos
Now for the fun part. In this section, we will go over a few attacks listed in the articles and demonstrate how they are detected and blocked by the proposed LDAPFW configuration.
1. Recon using Bloodhound
Let’s start as many attackers do – we will try to perform AD reconnaissance on our environment using SharpHound (a BloodHound data collector). Running the tool is simple enough – in this case, we just need to supply the hostname of our domain controller. However, we can see that we are not able to collect any AD objects or information on permissions from the domain controller.
Looking at the Event Log on our DC, we can see that the reason we were denied the search request was that we were blocked by LDAPFW. In this case, the LDAPFW rule that matched was rule #2: Block any Search requests that attempt to iteratively read sensitive attributes.
As a side note, LDAPFW always returns an insufficientAccessRights (50) error on block. This is done to not alert the user of the actual reason for denying the request (that we are using LDAPFW).
Search operation blocked as the scope is Subtree and several sensitive attributes were requested
2. Modifying a Machine’s SPN Attribute
Next, we’ll try to add a new SPN to a machine account as part of a targeted Kerberoasting attack. For this demo, we will mirror TrustedSec’s article (section 5.2.3) and use Powermad’s Set-MachineAccountAttribute to attempt to modify the machine’s ServicePrincipalName attribute.
Once again, we are blocked by LDAPFW; this time hitting rule #3, which specifies that remote hosts are not allowed to modify the ServicePrincipalName attribute.
3. Shadow Credentials
Lastly, let’s attempt a Shadow Credentials attack, which modifies a user’s KeyCredentialLink attribute. We will be using the Whisker tool which will automate the process for us.
And – guess what? Once again, we are blocked, thanks to our LDAPFW configuration. In this instance, we also hit rule #3, as the LDAP operation attempted to modify an unauthorized attribute.
Conclusion
We invite you to join the Zero Labs Slack Channel, where we and the community share more configurations for our open-source security tools. It is also a good place to share feedback, raise feature requests, and report any bugs.
In addition to LDAP Firewall, you can check out our other open-source projects on our website and Git repository.