Introduction to Attack Path Analysis with BloodHound

Active Directory
Time it takes to read this article 5 minutes.

Introduction / Overview

Legal & Ethical Disclaimer. This article is for education and authorized security testing only. Run these tools exclusively against directories you own or are explicitly contracted to assess. Unauthorized collection of Active Directory data is a crime in most jurisdictions. Always operate within the boundaries of a signed statement of work and rules of engagement.

Active Directory environments are graphs. Users belong to groups, groups have rights over computers, computers store credentials, and those credentials map to yet more privileges. Humans reason about this poorly — but a graph database does it instantly. BloodHound turns the messy reality of an AD domain into nodes and edges, then lets you ask the only question that matters during an engagement: "From where I stand now, what is the shortest path to Domain Admin?"

In this article you'll learn how the collector SharpHound gathers data, how that data lands in the neo4j graph database, how BloodHound visualizes attack paths, and how to write your own Cypher queries to find the shortest path to DA. We close with a full Blue Team section, because every edge BloodHound draws is also an edge you can break.

How It Works / Background

BloodHound has two halves:

  1. The collector (SharpHound) — a C# (or Python/Rust) tool that enumerates the domain over LDAP, SMB, and the SAMR/LSA RPC interfaces. It reads group memberships, ACLs (DACLs on objects), sessions (who is logged on where), local admin rights, GPO links, trusts, and Kerberos delegation settings.
  2. The analyzer (BloodHound GUI + neo4j) — SharpHound's JSON output is imported into neo4j. BloodHound renders the data as an interactive graph and ships pre-built queries; under the hood every query is Cypher, neo4j's graph query language.

The power comes from the edge abstraction. An edge like MemberOf, AdminTo, HasSession, GenericAll, WriteDacl, AddKeyCredentialLink, or CanRDP represents a concrete privilege escalation primitive. Chaining edges = chaining abuses. The shortest path between your owned principal and the Domain Admins group is, quite literally, your escalation playbook.

Modern BloodHound comes in two flavors: the legacy BloodHound Legacy (the classic Electron app) and BloodHound Community Edition (CE), which runs as Docker containers with a web UI. Both speak Cypher to neo4j and consume SharpHound output.

Prerequisites / Lab Setup

You need a lab AD domain (e.g., a Windows Server DC plus a couple of member machines) and a low-privilege domain user. Build BloodHound CE with Docker:

# Pull the official compose file and start the stack
curl -L https://ghst.ly/getbhce -o docker-compose.yml
docker compose up -d

# BloodHound CE serves the web UI on http://localhost:8080
# A randomly generated admin password is printed in the container logs:
docker compose logs bloodhound | grep -i "Initial Password"

This launches three containers: the BloodHound app, a neo4j database (Bolt on 7687, browser on 7474), and a PostgreSQL instance for app metadata. Log into neo4j's own browser at http://localhost:7474 with the default neo4j:bloodhoundcommunityedition if you want to run raw Cypher outside the UI.

Attack Walkthrough / PoC

Step 1 — Collect with SharpHound

From a domain-joined Windows host (or any host with network access and valid creds), run SharpHound. The All collection method is the most thorough:

# Run from a domain context; writes a timestamped ZIP of JSON files
.\SharpHound.exe -c All --zipfilename loot

# Targeted, lower-noise collection (no session loop, no local-group RPC)
.\SharpHound.exe -c DCOnly --zipfilename quiet

-c All includes Session enumeration (querying every computer for logged-on users via NetWkstaUserEnum / NetSessionEnum), which is noisy. -c DCOnly pulls everything available from the Domain Controller via LDAP alone — far stealthier, at the cost of session data.

If you're operating from Linux without dropping a binary, use the Python collector:

# bloodhound.py — collect over the network with creds only
bloodhound-python -u 'lowpriv' -p 'P@ssw0rd!' \
  -d corp.local -ns 10.10.10.10 -c All --zip

Step 2 — Ingest into neo4j

In BloodHound CE, open the UI, go to Administration → File Ingest, and drag the ZIP in. The app parses the JSON and writes nodes/edges into neo4j. For BloodHound Legacy, you simply drag the ZIP onto the graph canvas.

Step 3 — Mark what you control and find the path

Right-click your compromised user and select Mark User as Owned. Then use the pathfinding bar: set the start node to your owned principal and the end node to DOMAIN ADMINS@CORP.LOCAL. BloodHound runs a shortest-path Cypher query and draws every edge.

You can run that query yourself. Here is the canonical shortest path to DA in Cypher:

// Shortest path from any Owned principal to the Domain Admins group
MATCH (n {owned:true}), (g:Group)
WHERE g.objectid ENDS WITH '-512'   // RID 512 = Domain Admins
MATCH p = shortestPath((n)-[*1..]->(g))
RETURN p

Some other queries worth memorizing:

// Every principal with an unconstrained path to Domain Admins
MATCH p=shortestPath((u:User)-[*1..]->(g:Group {name:'DOMAIN ADMINS@CORP.LOCAL'}))
RETURN p LIMIT 25

// Kerberoastable users (have an SPN) — feed these into Hashcat
MATCH (u:User {hasspn:true}) RETURN u.name, u.serviceprincipalnames

// Dangerous ACL edges from an owned principal
MATCH (n {owned:true})-[r:GenericAll|GenericWrite|WriteDacl|WriteOwner|AddKeyCredentialLink]->(t)
RETURN n.name, type(r), t.name

Step 4 — Walk the edges

Each edge has a known abuse. A typical chain looks like: your user is MemberOf a help-desk group that has GenericAll over a service account; that service account hasspn, so you Kerberoast it and crack the hash; the cracked account is AdminTo a server where a Domain Admin has an active session, and you dump their credentials. See Kerberoasting and Abusing AD ACLs and DACLs for the per-edge tradecraft, and DCSync Attacks for the final step once you hold replication rights.

Mermaid Diagram

Introduction to Attack Path Analysis with BloodHound diagram 1

The diagram shows the attack flow: a low-privilege user chains group membership, an ACL edge, Kerberoasting, local admin rights, and a harvested session to reach Domain Admin and ultimately DCSync the domain.

Detection & Defense (Blue Team)

BloodHound is equally a defensive tool — run it against your own domain and remediate the edges.

Collection-time detection.

  • SharpHound's Session collection generates a burst of SMB connections and SAMR/LSARPC calls from one host to many. Hunt for NetSessionEnum / NetWkstaUserEnum fan-out and anomalous LDAP enumeration. Sysmon plus a SIEM correlation rule on "one source enumerating hundreds of hosts in minutes" is highly effective.
  • Enable verbose AD LDAP audit logging and watch for broad queries pulling nTSecurityDescriptor, servicePrincipalName, and msDS-KeyCredentialLink across the directory.
  • Honeypot accounts: a fake high-privilege user with an SPN (a "honey SPN") that no legitimate service ever requests. Any Kerberoast/TGS request for it (Event ID 4769) is a near-certain alert.

Reduce the attack surface (kill the edges).

  • Prune ACLs. Edges like GenericAll, WriteDacl, WriteOwner, and AddKeyCredentialLink are the most abused. Audit DACLs with PowerShell and remove inherited or stale dangerous rights:
# Find non-default ACEs granting GenericAll/WriteDacl on AD objects
Get-ADObject -Filter * -Properties nTSecurityDescriptor |
  ForEach-Object {
    $_.nTSecurityDescriptor.Access |
      Where-Object { $_.ActiveDirectoryRights -match 'GenericAll|WriteDacl|WriteOwner' }
  }
  • Tier your administration. Implement the Microsoft tiered admin model (Tier 0/1/2) so Domain Admins never log on to workstations or member servers. This breaks the HasSession → Domain Admin edge that BloodHound relies on. Pair it with Authentication Policy Silos to restrict where privileged accounts can authenticate.
  • Mitigate Kerberoasting. Use gMSA/dMSA (Group Managed Service Accounts) so passwords are 120+ characters and auto-rotated, making cracking infeasible. Enforce AES-only Kerberos (msDS-SupportedEncryptionTypes) to deny RC4 tickets.
  • Block credential theft. Enable LSASS protection (RunAsPPL), Credential Guard, and RestrictedAdmin RDP mode to prevent harvesting the sessions that turn a foothold into DA.

This maps to MITRE ATT&CK T1087 (Account Discovery), T1069 (Permission Groups Discovery), T1482 (Domain Trust Discovery), and T1558.003 (Kerberoasting).

Conclusion

BloodHound doesn't find new vulnerabilities — it reveals the path through privileges you already deployed. SharpHound collects the graph, neo4j stores it, and a single Cypher shortestPath query collapses weeks of manual enumeration into one click. For defenders, the lesson is identical: the shortest path to DA you can see in BloodHound is the one an attacker will take, so close it first. Run BloodHound against your own domain quarterly, mark your most-exposed accounts as owned, and remediate until that path no longer exists.

References

Comments

Copied title and URL