BloodHound is a tool developed by penetration testers and red teamers to better identify and visualize attack paths in Active Directory. However, that doesn’t mean it can’t also be used effectively by admins or the blue team.
What is BloodHound?
BloodHound consists of two or three components:
- Collector (collects the information)
- Database and UI (visualizes the collected data)
Collector
The Collector is a small program that gathers information about Active Directory and writes it to a file.
The program is independent of the database and UI and only collects data for further use.
Database and UI
The second component of BloodHound is a Neo4j database and a UI for it. Once we have collected the data with the Collector, it can be imported via the UI.
This component is where we spend most of our time. It offers a way to query and visualize the data.
Installation
For the actual installation, I refer to the GitHub repo or the official documentation:
https://github.com/SpecterOps/BloodHound/wiki
I always install BloodHound on a Linux VM, but that’s a matter of preference.
The Collector can be downloaded either directly from the BloodHound UI or from here on GitHub:
https://github.com/BloodHoundAD/SharpHound/releases
After a successful installation, the following URLs/ports should be accessible:
- http://localhost:8080/ui/login
- http://localhost:7474/ and port 7687
Usage
Collector
First, we run the Collector to gather the data. It is important that the version of the Collector matches the version of the UI, as the file format sometimes changes. The Collector must be run on a system that can access the domain controller. The easiest way is to run the Collector on a domain computer under a domain account. The account doesn’t need special permissions.
Note: The Collector will most likely be detected as malware. Therefore, an exception must be added. Also, ensure that the program comes from a trusted source.
In most cases, simply double-clicking the exe file is enough. Depending on the size of the Active Directory, it may take a little while to complete (from a few seconds to several hours). In the end, a few JSON files or a ZIP file should appear next to the exe file. If this doesn’t happen, sometimes simply running it again helps.
Database and UI
This component should now be running and accessible via a web interface. Using the import button, we can upload the collected data. Again, depending on the size of the Active Directory, this may take a little while.
Then, we can already try out the built-in queries and, for example, visualize who the domain admins are. If this query returns many accounts, it is usually already a pentest finding. However, this can also be queried easily with native tools. The more interesting queries are a bit more complex. I will cover these in the next chapter.
Queries
In my opinion, the BloodHound UI is not so useful for admins. It becomes more interesting when you use the Neo4j console. In this, you make queries in the “Cypher” query language and get textual output.
You can access it in your browser at http://localhost:7474/browser/. The default login credentials are:
User: neo4j
Pass: bloodhoundcommunityedition
The query language is unfortunately not easy to understand. It takes a little time to get used to it. Here are some useful queries:
Old Passwords
The following query outputs accounts that haven’t changed their password in a long time. Regular users don’t have to change their password regularly. However, if other accounts appear here, it should be checked:
MATCH (u:User)
WHERE u.enabled = true
AND u.pwdlastset < (datetime().epochseconds - (1825 * 86400))
RETURN u.name as Username, datetime({epochSeconds: toInteger(u.pwdlastset)}) as PwdLastSet order by u.pwdlastset
The query specifically checks if there are active users whose password hasn’t been changed for 5 years (= 1825 days * 86400 seconds per day). The data will then be displayed in a table.
Domain Admins with Old Passwords
This query is restricted to domain admins. Since these accounts are particularly important, accounts with passwords older than 3 years are listed:
MATCH p=(n:Group)<-[:MemberOf*1..]-(u) WHERE n.objectid =~ "(?i)S-1-5-.*-512" WITH u MATCH (u)
WHERE (u.pwdlastset < (datetime().epochseconds - (1095 * 86400)))
WITH u.name AS Username, datetime({epochSeconds: toInteger(u.pwdlastset)}) AS PwdLastSet
ORDER BY u.pwdlastset RETURN DISTINCT Username,PwdLastSet
Unused Users
The following query outputs active accounts that haven’t changed their password for 5 years and haven’t logged in for 5 years:
MATCH (u:User)
WHERE u.enabled = true
AND u.pwdlastset < (datetime().epochseconds - (1825 * 86400)) and u.lastlogontimestamp < (datetime().epochseconds - (1825 * 86400))
RETURN u.name as Username, datetime({epochSeconds: toInteger(u.pwdlastset)}) as PwdLastSet, datetime({epochSeconds: toInteger(u.lastlogontimestamp)}) as LastUsed order by u.pwdlastset
Percentage of Active Users
Finally, a query that outputs the percentage of active accounts. This is sometimes helpful to see if there are many “zombie” accounts in AD.
// Count the total number of users
MATCH (uTotal:User)
with count(uTotal) as TotalUsers
// Count the enabled users
match (uEnabled:User)
where uEnabled.enabled
with TotalUsers, count(uEnabled) as EnabledUsers
return TotalUsers, EnabledUsers, EnabledUsers/(TotalUsers/100.0) as PercentageEnabled
Summary
As we can see, BloodHound can also be interesting for admins. The queries are just examples. There are many other queries that could be useful depending on the environment.
+43 720 971425 |
martin@vidrasec.com |
Book appointment |