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 ADMINS@DOMAIN.LOCAL>'})) 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​