BloodHound visualizes Active Directory as a graph, revealing attack paths that are otherwise invisible. One Cypher query can expose a path from a compromised help desk account to Domain Admin.
Installation
# BloodHound CE (Community Edition — Docker) git clone https://github.com/SpecterOps/BloodHound.git cd BloodHound/examples/docker-compose/ docker compose up -d
# Access at http://localhost:8080 # Default creds: admin / (generated on first run, check docker logs)
# Collect specific methods .\SharpHound.exe -c DCOnly # DC data only (faster) .\SharpHound.exe -c Session # active sessions .\SharpHound.exe -c ACL # ACL/permissions .\SharpHound.exe -c Trusts # domain trusts .\SharpHound.exe -cGroup# group membership .\SharpHound.exe -c LocalAdmin # local admin rights
# Stealth options .\SharpHound.exe -c All --stealth# avoid noisy LDAP queries .\SharpHound.exe -c All --ExcludeDomainControllers
# Output options .\SharpHound.exe -c All --outputdirectory C:\temp --zipfilename output.zip .\SharpHound.exe -c All --randomfilenames# randomize output file names
# Collect with credentials bloodhound-python -u user -p password -ns DC_IP -d domain.local -c all
# With hash (Pass-the-Hash) bloodhound-python -u user --hashes :NT_HASH -ns DC_IP -d domain.local -c all
# Kerberos auth KRB5CCNAME=ticket.ccache bloodhound-python -u user -ns DC_IP -d domain.local -c all -k --no-pass
# Specific collection bloodhound-python -u user -p pass -ns DC_IP -d domain.local -c DCOnly bloodhound-python -u user -p pass -ns DC_IP -d domain.local -c Group,ACL,Trusts
# Output to folder bloodhound-python -u user -p pass -ns DC_IP -d domain.local -c all --zip -o /tmp/bh/
Uploading Data
BloodHound → Upload Data button → select ZIP or JSON files # Or drag-and-drop into the UI
# BloodHound CE API upload curl -X POST http://localhost:8080/api/v2/file-upload \ -H "Authorization: Bearer TOKEN" \ -F "file=@bloodhound_output.zip"
Built-in Analysis Queries
In BloodHound’s Analysis tab:
# DomainDominance paths "Find Shortest Paths to Domain Admins" "Find Principals with DCSync Rights" "Find All Paths from Domain Users to Domain Admins" "Find Computers where Domain Users are Local Admin"
# Kerberos attacks "Find Kerberoastable Users with Path to DA" "Find Kerberoastable Members of High Value Groups" "Find AS-REP Roastable Users (DontReqPreAuth)"
# Delegation "Find Computers with Unconstrained Delegation" "Find Computers with Constrained Delegation" "Find Users with Constrained Delegation"
# Lateral movement "Find Shortest Paths to Domain Controllers" "Find Machines where Domain Admins have Active Sessions" "Find All Paths from Kerberoastable Users to Domain Admin"
Custom Cypher Queries
Open Raw Query bar in BloodHound:
// Find all users with path to DA in <5 hops MATCH p=shortestPath((u:User)-[*1..5]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"})) WHERE u.enabled = true RETURN p
// Find computers where a specific user is local admin MATCH (u:User {name:"USER@DOMAIN.LOCAL"})-[r:AdminTo]->(c:Computer) RETURN c.name
// Find all AD groups a user is member of (recursively) MATCH p=(u:User {name:"USER@DOMAIN.LOCAL"})-[:MemberOf*1..]->(g:Group) RETURN g.name
// Kerberoastable users with admin rights somewhere MATCH (u:User {hasspn:true})-[r:AdminTo|MemberOf*1..]->(c:Computer) WHERE u.enabled = true RETURN u.name, c.name
// Find users with DCSync rights MATCH (u)-[:MemberOf*0..]->(g)-[:DCSync]->(d:Domain) RETURN u.name, d.name
// Find computers with sessions of DA members MATCH (c:Computer)-[:HasSession]->(u:User)-[:MemberOf*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"}) RETURN c.name, u.name
// Find accounts with Password Never Expires MATCH (u:User {pwdneverexpires:true, enabled:true}) RETURN u.name, u.description
// Find accounts with empty description (often contain passwords) MATCH (u:User) WHERE u.description IS NOT NULL AND u.description <> "" RETURN u.name, u.description
// Shortest path from owned to DA MATCH p=shortestPath((u:User {owned:true})-[*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"})) RETURN p
// Find all WriteDACL relationships MATCH (u)-[r:WriteDacl]->(t) WHERE u.name <> t.name RETURN u.name, type(r), t.name
// Accounts with GenericAll on other accounts MATCH (u)-[:GenericAll]->(t:User) RETURN u.name, t.name
// Find AS-REP roastable with a path to DA MATCH p=shortestPath((u:User {dontreqpreauth:true})-[*1..]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"})) WHERE u.enabled = true RETURN p
Marking Owned Objects
# In BloodHound UI: # Right-click any node → Mark as Owned
# Via Cypher (bulk mark) MATCH (u:User) WHERE u.name IN ["USER1@DOMAIN.LOCAL", "USER2@DOMAIN.LOCAL"] SET u.owned = true
# Mark compromised computers MATCH (c:Computer) WHERE c.name IN ["WORKSTATION01.DOMAIN.LOCAL"] SET c.owned = true
Marking High Value Targets
// Add to high value manually MATCH (n {name:"TARGET@DOMAIN.LOCAL"}) SET n.highvalue = true
// Remove false positive from high value MATCH (n:Computer {name:"SOME_SERVER.DOMAIN.LOCAL"}) SET n.highvalue = false
# Collect with service principal ./azurehound -u user@domain.com -p password list --tenant "TENANT_ID" -o output.json
# With client ID and secret ./azurehound -a CLIENT_ID -s CLIENT_SECRET --tenant TENANT_ID list -o azure.json
# With refresh token ./azurehound -r REFRESH_TOKEN --tenant TENANT_ID list -o azure.json
Quick Analysis Workflow
1. Upload SharpHound/bloodhound-python ZIP 2. Analysis → "Find Shortest Paths to Domain Admins" 3. If no path from owned useryet: - Mark your current useras Owned - Analysis → "Shortest Path from Owned Principals to Domain Admins" 4. Look for ACL-based edges: WriteDACL, GenericAll, GenericWrite, ForceChangePassword 5. Look for Kerberoastable nodes in the path 6. Use "Find Computers where Domain Users are Local Admin" for quick wins 7. Check BloodHound "Outbound Object Control" on your owned usernode
Node Property Reference
// User properties worth checking u.enabled // account enabled u.hasspn // kerberoastable u.dontreqpreauth // AS-REP roastable u.pwdneverexpires // password never expires u.lastlogontimestamp // last logon u.description // may contain passwords u.admincount // protected by AdminSDHolder
// Computer properties c.unconstraineddelegation // unconstrained delegation c.operatingsystem // OS version c.lastlogontimestamp // last logon
// Group properties g.admincount // high privilege group
No comments yet. Be the first.