Skip to main content

Bloodhound

Ingestors (offical collectors)

info

SharpHound requires .NET > 3.5, but can be ran from a non domain joined computer.

. .\SharpHound.ps1 
Invoke-BloodHound -collectionmethod all [-jsonfolder c:\windows\temp]
SharpHound.exe -c all,GPOLocalGroup --NoSaveCache [-jsonfolder c:\windows\temp] [-EncryptZip]

Running the collector from a non domain-joined computer

Use the standard collection procedure with the runas /netonly trick.

runas /netonly /user:domain\username cmd.exe 

Non official collectors

info

These collectors do not include all features correctly such as delegations and sessions. It is recommended to use a non domain-joined VM (see above).

bloodhound --collectionmethod all
pip install ldap3 dnspython ldapdomaindump
ldapdomaindump -u "DOMAIN\user" <ip>

BloodHound GUI

Custom queries

info

Download customqueries.json and put it under the following path /root/.config/bloodhound/customqueries.json.

List of current custom queries:

  • ALL Path from DOMAIN USERS to High Value Targets
  • Find Servers where DOMAIN USERS can RDP To
  • Top Ten Computers with Most Admins
  • All Shortest Path - Owned to HighValue
  • Find all other Rights DOMAIN USERS shouldn’t have

Shortcuts

  • Ctrl: Change node labels (Hide, Default threshold, Show all)
  • Space: Search amongst the currently displayed nodes
  • Ctrl+R: Restart Bloodhound (in case of a crash)

Cypher Queries

danger

These commands cannot be run in bloodhound as they query directly the db, prefer the neo4j api or web browser http://localhost:7474.

Find potential vulnerable systems

MATCH (H:Computer) WHERE H.operatingsystem =~ '(?i).*(2000|2003|2008|xp|vista|me).*' RETURN H

Find users with reversible encryption password

MATCH (u:User) WHERE NOT u.userpassword IS null RETURN u.name,u.userpassword

Find Shortest path with a condition on start, end and middle nodes

MATCH (a) WHERE <CONDITION on a which is the start node>
MATCH (b) WHERE <CONDITION on b which is the end node>
MATCH p=allShortestsPaths((a)-r[:MemberOf|GenericalAll|<ANY OTHER RELATION>*1..]->(b))
WITH p, nodes(p)[1..-1] as nodeslist
WHERE ALL( n in nodeslist[1..] WHERE <CONDITION on intermediate nodes>)
RETURN p

AD Metrics

Very heavy query

Percentage User to Target group + Distance/Cost/ComputerTouched.

MATCH (tx:User),
p = shortestPath((x:User)-[r*1..]->(g:Group {name:'<DOMAIN [email protected]>'})) WITH g.name as G,
COUNT(DISTINCT(tx)) as TX,
COUNT(DISTINCT(x)) as X, ROUND(100*AVG(LENGTH(RELATIONSHIPS(p))))/100 as H,
ROUND(100*AVG(length(filter(z in extract(r in relationships(p)| type(r)) where z<>'MemberOf'))))/100 as C,
ROUND(100*AVG(length(filter(y in extract(n in nodes(p)|LABELS(n)[0]) WHERE y='Computer'))))/100 AS T
WITH G,TX,X,H,C,T,
ROUND(100*(100.0*X/TX))/100 as P
RETURN {
TotalCount: TX,
PathCount: X,
Percent: P,
HopAvg: H,
CostAvg: C,
TouchAvg: T
}

Set node as owned from file (for examples hashes cracked with Hashcat)

info

The following script sets the user nodes provided as Owned and write the password in the Notes field

The Hash file MUST have one user:password per line

It is preferable to close Bloodhound GUI when running the script

CURRENTLY, IT WILL OVERRIDE ANY NOTE SAVED FOR AN OWNED USER

pip3 install py2neo
export NEO4J_USER=<neo4j>
export NEO4J_PASSWORD=<CHANGEME>
python3 bloodypasswords.py <DOMAIN FQDN FOR EX: CORP.LOCAL> <USER_HASH_FILE>

References