This is the first blog post of many in a series to expand on common ways we take over client networks. It will cover one of the most feature-rich parts of an enterprise network for attackers, Active Directory (AD). By far one of the most interesting parts of hacking due to the sheer complexity of the relationships, abusing AD often leads to spotting critical vulnerabilities that don’t show up during network vulnerability scanning, cybersecurity risk assessments, or compliance evaluations.  

AD is nearly ubiquitous across Windows-based environments (with a slow yet sure incorporation of AzureAD now seen for organizations migrating to the cloud). It is also a handy directory service that provides a centralized and standardized means of organizing a network.

Attackers (and providers that do pen testing as a service) have several means of enumerating an AD environment, with the most common and robust being “Bloodhound.” Bloodhound maps out everything in graph form — making it easy to see potential escalation paths from specific users or groups depending on their permissions, with excessive permissions often being the most damaging AD misconfiguration seen within organizations. 

The analysis done in this post through Bloodhound, the Neo4j interface, assumes you have installed and configured both with data imported from a target network.

Quick Bloodhound Tips (What to Consider Before Network Penetration Testing):

1. Detection: You’ll first need to gather the data via Sharphound or some other method. The customer should have cybersecurity monitoring controls to catch this. If not, the report should include this as a finding with the remediation discussing detection methods.

2. Azure: Even if controls like Multi-Factor Authentication (MFA) are enabled, you can often gather a ton of data externally and import it into Bloodhound via Azurehound. Analyze if the target organization has a tenant and collect that data if it’s in scope. 

  1. Example:
    azurehound.exe list -u "user" -p "pass" -t "tenantName.onmicrosoft.com" -o "output.json"

3. Settings: In the settings, we like to enable Dark Mode, Query Debug Mode, and “Always Display” Edge Label Display, and Node Label Display.

4. Raw Query: Start by looking at the queries Bloodhound performs via Raw Query at the bottom of the GUI. Understanding how to craft your own queries will become incredibly useful as you evolve your analysis techniques.

5. Understanding Permissions: Right-click on the edge (line connecting two points) and click “Help” to learn more about that permission and how to abuse it.

6. Multiple Networks: We like to switch between neo4j databases for various networks. You can quickly set up a new database by modifying the neo4j configuration file: 

(/etc/neo4j/neo4j.config) + restart the service.

You’ll need to set up a new user the first time via neo4j before logging into the Bloodhound:

  1. (Original) initial.dbms.default_database=network1
  2. (Modified) initial.dbms.default_database=network2

7. Certificate Templates: You should gather certificate template data via certipy and import it into your Bloodhound GUI. This will help you understand permission abuse paths with certificate templates within Active Directory. Certipy supports “-bloodhound” and “-old-bloodhound” to export the data as a .zip for Bloodhound. This is assuming you’re using the version of Bloodhound within Kali Repos, and not Bloodhound CE and/or Enterprise.

8. Sessions: Getting session data is incredibly useful for privilege escalation analysis. This is very noisy on the network, so consider the assessment goals and OPSEC considerations.

  1. Sometimes, session data can only be gathered by a computer already connected to AD, so running from Kali may pull back nothing.
  2. You may also need higher privileges to get a good picture of active sessions. We will often run sharphound again with higher privileges after acquired to continue to hunt for additional paths.
  3. Session data is volatile and changes as sessions drop, etc. You’ll want to periodically get a fresh set of session data to evaluate escalation paths.
  4. Session data requires multiple runs to gather a more complete picture. Per Sharphounds documentation, a single session collection may gather 5-15% of the actual sessions. For this reason, they have a session looping collection command option:
    C:\> SharpHound.exe --CollectionMethods Session --Loop

9. Crackhound: If you have a large list of compromised users, you can more easily import them and mark them as owned via Crackhound: https://github.com/trustedsec/CrackHound

10. Custom Queries: There are lots of good custom queries that extend the built-in analysis queries. You can set up your Bloodhound with additional queries by modifying the following file:

(~/.config/bloodhound/customqueries.json)
  1. Here is a link to a good set of custom queries: https://github.com/hausec/Bloodhound-Custom-Queries
  2. You may also consider making your own modifications to re-run some of your custom queries more easily.

We find analyzing Users, Computers, and Groups very useful to get a general idea of the AD environment. You can find interesting things based on titles, descriptions, and other attributes, like how frequently passwords change. After understanding the AD environment, we like to look at AD from the bottom up and top down. Below, we will describe how to go about this in more detail:

  1. Gain an initial understanding of the environment
  2. Common starting points and how to escalate (Bottom-Up Approach)
  3. Desirable ending points and who can reach them (Top-Down Approach)

Of course, there are many other analysis perspectives to consider. Still, fundamentally, this can be a great place to start learning the target AD environment and pulling out some quick wins during vulnerability assessment and penetration testing exercises.

Many penetration testing teams and hackers rush to mark their current user-owned and check the shortest paths to Domain Admins in Bloodhound. This is undoubtedly a useful analysis technique, but you shouldn’t skip analyzing the environment in general. 

We like to execute the following searches and will modify them based on various interesting attributes. For example, consider the following query within the neo4j interface to pull a list of all users and their descriptions:

  • List Users + Descriptions:
    `MATCH (u:User) return u.name, u.description`

You may also want to pull a list of users and their titles:

  • List Users + Title: 
    `MATCH (u:User) return u.name, u.title`

If you want to return the full list of properties, simply return the u object, then look at the complete properties and decide what information you might want to return in a query for your analysis:

  • List Full User Data: 
    `MATCH (u:User) return u`

Here are some examples of leveraging some of the user properties with your search query:

  • Show only enabled Users: 
    `MATCH (u:User {enabled: true}) return u.name`

[Note: Remember that disabled users can still provide relevant escalation paths. This is often a misconception. You might be thinking, “They’re disabled, and I can’t use them.” Consider the following: You have “GenericAll” over a disabled account, and that account has access to another system, which expands your access. If you have “GenericAll,” you can enable that account and change the password, then use it. This is also why simply disabling an account doesn’t always remove the privilege escalation risk, so be mindful of this when suggesting remediation.]

  • Show only enabled users with some administrative privileges within the domain:
    `MATCH (u:User {enabled: true, admincount: true}) return u.name`
  • You can also return a count of enabled users with admin access via:
    `MATCH (u:User {enabled: true, admincount: true}) return count(u.name)`

This blog isn’t scoped around making you an expert with the Cypher Query Language, but enough to get your feet wet and play around with queries.

Below are some additional queries to learn more about the targeted AD environment:

  • List Groups + Description
    'MATCH (u:Group) return u.name, u.description`
  • List Computers + Descriptions
    `MATCH (u:Computer) return u.name, u.description`
  • Analysis Tab > Map Domain Trusts: You might find the environment has a domain trust setup that can allow for potentially expanded scope and abuse paths. Be sure to check the Rules of Engagement (ROE) and the customer to identify if the other domain(s) are in scope.
    • If these additional domain(s) are in scope, you should run Sharphound to gather data for those domain(s) and import them to Bloodhound.
  • Analysis Tab > List all Kerberoastable Users: These users are set up as service accounts within AD and have SPN records set. You can request a TGS for the user and attempt to crack the password hash from any user account within the domain.
  • Analysis Tab > Find Principals with DCSync Rights: These users have special permissions to perform AD replication and effectively get the entire AD database. Sometimes, this permission is given to unprotected accounts, like the flaw with AD Connect Microsoft had in 2017. Many networks still have these AD Connect service accounts enabled today with this privilege and unprotected (AdminCount=False).
  • Passwords: Identify users who haven’t changed their password in over 90 days (you can modify the query below to be over a year, two years, etc.). This is useful for targeting accounts with older passwords that might not follow the organization’s password policy:
    MATCH (u:User {enabled: true}) WHERE u.pwdlastset > 0
    WITH u.name AS name, u.description AS description, u.enabled AS enabled, datetime({ epochSeconds:toInteger(u.pwdlastset) }) AS pwdlastset, duration.inDays(datetime({ epochSeconds:toInteger(u.pwdlastset) }), date()).days AS days_since_pwdlastset
    WHERE days_since_pwdlastset > 90
    RETURN name, description, days_since_pwdlastset, pwdlastset 
    ORDER BY days_since_pwdlastset DESC

Armed with the initial understanding of the environment, we can now move into looking up from common starting points for network penetration testing through AD, which can include: 

  1. Compromised User(s)
  2. Standard Groups
  3. Compromised Computer(s)

An example of this is taking your compromised users and marking them as owned within Bloodhound — allowing you to check several built-in path queries that start from owned users. Additionally, we like to analyze all the outbound controls from this starting point to see what the user can effectively do:

You can apply this same approach to Group(s) and Computer(s) that you’ve compromised or have access to by means of any standard AD account. We have often found interesting abuse paths mapped to built-in inherited groups (EVERYONE@domain.local, Domain Users@domain.local, USERS@domain.local, etc.) 

This goes back to understanding the domain during user analysis to get an idea of what common groups the users comprise. Many will be built-in to AD, while others will be specific to the target network. 

Below is an example of a compromised user’s transitive outbound control rights and some interesting permissions you’d want to investigate:

The top-down approach, we find, is less commonly leveraged when analyzing networks but provides a lot of valuable escalation paths. Hackers often think in terms of: “I got this account, so now what can I do?” but fail to think about objects in the network with interesting permissions and who can touch those objects. 

Of course, this is beyond Domain Admins and Enterprise Admins. Hackers often know to look here, but AD is so complex you can have many objects that are effectively “shadow” domain admins by having paths to reach those permissions or have virtually the same permissions, just not be in those groups.

We like to figure out who has the most outbound rights within the AD environment. These are folks like Domain and Enterprise Admins, but you might also find some odd developer group or random user amongst the list of having excessively high outbound permissions. These other objects can have fewer controls applied to them and may offer very enticing escalation paths that the organization might have otherwise missed. 

To identify AD objects with the most outbound rights, we run the following neo4j queries (please note some of these queries can take a lot of time to finish, especially the transitive outbound rights):

Top 100 Outbound Control Rights (First Degree Object Control)

MATCH p=(u)-[r1]->(n) WHERE r1.isacl=true
WITH u.name as name, LABELS(u)[1] as type,
COUNT(DISTINCT(n)) as controlled
WHERE name IS NOT NULL
RETURN type, name, controlled
ORDER BY controlled DESC
LIMIT 100

Top 100 Outbound Control Rights (Group Delegated Object Control)

MATCH p=(u)-[r1:MemberOf*1..]->(g:Group)-[r2]->(n) WHERE r2.isacl=true
WITH u.name as name, LABELS(u)[1] as type, g.highvalue as highly_privileged,
COUNT(DISTINCT(n)) as controlled
WHERE name IS NOT NULL
RETURN type, name, highly_privileged, controlled
ORDER BY controlled DESC
LIMIT 100

Top 50 Outbound Control Rights (Transitive Object Control)

MATCH p=shortestPath((u)-[r1:MemberOf|AddMember|AllExtendedRights|ForceChangePassword|GenericAll|GenericWrite|WriteDacl|WriteOwner|Owns*1..]->(n))
WHERE u<>n
WITH u.name as name, LABELS(u)[1] as type,
COUNT(DISTINCT(n)) as controlled
WHERE name IS NOT NULL
RETURN type, name, controlled
ORDER BY controlled DESC
LIMIT 50

Once we have the list of users, groups, etc., that have the most outbound control rights, we will start to understand them better by pulling them up in Bloodhound and then analyze what they can touch by looking at all the outbound control rights. The graphs here might be large and difficult to draw, so you might consider just leveraging the Bloodhound Pathfinding feature:

After understanding the outbound permissions a bit more, turn your attention to the inbound control rights to see who can effectively reach these high-privilege objects:

By evaluating the inbound control rights, you can identify potential paths to reach this target. You might find you need to get to Computer B, and then you can get this user and establish permission you need to take over the entire network. From here, what seemed like a daunting task of taking over a 100,000 computer environment is as simple as reaching this one computer or user.

Below is an example of how compromising a single group leads to full domain compromise through several permission abuse hops:

Active Directory is loaded with such powerful and interesting data to abuse to take over networks. 

Today, it stands as the most interesting data source for the BPL red team pen testing experts to effectively demonstrate the risk of what an attacker could do to a network. 

While this blog post only scratches the surface of all the amazing data within AD, it has hopefully inspired you to dive deep into AD on your next engagement and challenge yourself to “break the cycle” by finding some vulnerabilities that have been missed for years.

For some continued reading, check out these other links: