| name | bloodhound |
| description | BloodHound — cartographie et analyse des relations Active Directory, collecteurs (SharpHound, AzureHound), requêtes Cypher personnalisées, attaque des chemins de privilèges, ACL abuse, ACE abusives, et optimisation des attaques AD. |
BloodHound — Analyse des Chemins d'Attaque AD
Présentation
BloodHound (BH) est un outil de cartographie des relations Active Directory. Il identifie les chemins d'attaque cachés entre les objets du domaine.
Composants :
- Collecteur (SharpHound.exe / AzureHound.ps1) → collecte les données AD
- Interface (bloodhound GUI) → visualisation des graphes
- Base (Neo4j) → stockage des données de graphe
Installation :
sudo apt install bloodhound
sudo neo4j console
sudo systemctl start neo4j
git clone https://github.com/BloodHoundAD/BloodHound.git
cd BloodHound && npm install && npm run build
Collecteurs
SharpHound.exe (Windows — .NET)
SharpHound.exe -c All
SharpHound.exe -c Group
SharpHound.exe -c LocalGroup
SharpHound.exe -c Session
SharpHound.exe -c ACL
SharpHound.exe -c Container
SharpHound.exe -c ObjectProps
SharpHound.exe -c DCOM
SharpHound.exe -c PSRemote
SharpHound.exe -c RDP
SharpHound.exe --domain DOMAIN --ldapuser admin --ldappass Password123
SharpHound.exe -c All --CollectionMethod DCOnly
SharpHound.exe -c Group,LocalGroup,Session --throttle 500
SharpHound.exe --LdapPassword Password123 --CertificatePath cert.pfx
SharpHound.exe -c All --OutputDirectory C:\temp\
SharpHound.ps1 (PowerShell)
# Charger le script
Import-Module .\SharpHound.ps1
# Collecte complète
Invoke-BloodHound -CollectionMethod All
# Avec credentials
$cred = Get-Credential
Invoke-BloodHound -CollectionMethod All -Credential $cred
# DC Only (moins bruyant)
Invoke-BloodHound -CollectionMethod DCOnly
# Options :
# -Stealth : Skip ping et connexions SMB
# -Loop : Collecte continue (boucle)
# -Interval N : Intervalle entre collectes (minutes)
# -Threads N : Threads (augmenter pour les grands domaines)
# -SearchForest : Rechercher dans toute la forêt
AzureHound (Azure AD)
azh.exe -u admin@domain.com -p Password123
BloodHound.py (Linux)
impacket-bloodhound -c all -u admin -d DOMAIN -dc-ip 192.168.1.10
impacket-getTGT DOMAIN/user:Password123
export KRB5CCNAME=/path/to/ticket.ccache
bloodhound-python -c All -d DOMAIN -dc DC -k
Import des données dans BloodHound
sudo neo4j console
sudo systemctl start neo4j
bloodhound
Requêtes pré-construites (GUI)
Analyse rapide — Les 5 questions essentielles
Requêtes de recherche de privilèges
"Find Computers where Domain Users are Local Admin"
"Find Computers where Domain Users have RDP access"
"Find Computers where Domain Users have SQL Admin access"
"Find all Active Sessions"
"Node Mapper"
Requêtes Cypher — Le cœur de BloodHound
Concepts Cypher
// Syntaxe de base
MATCH (n:User) RETURN n LIMIT 10 // 10 users
MATCH (n:Computer) RETURN n LIMIT 10 // 10 computers
MATCH (n:Group) RETURN n.name LIMIT 10 // Noms des groupes
MATCH (n:User {name:"ADMIN@DOMAIN.LOCAL"}) RETURN n // User spécifique
Requêtes d'analyse avancées
1. Chemin le plus court vers DA
// D'un utilisateur spécifique vers Domain Admins
MATCH (u:User {name:"USER@DOMAIN.LOCAL"}),
(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"})
MATCH p = shortestPath((u)-[*1..]->(g))
RETURN p
// D'un groupe vers DA
MATCH (g1:Group {name:"GROUPE@DOMAIN.LOCAL"}),
(g2:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"})
MATCH p = shortestPath((g1)-[*1..]->(g2))
RETURN p
2. Trouver tous les chemins vers DA
// Tous les chemins (pas seulement le plus court)
MATCH (u:User {name:"USER@DOMAIN.LOCAL"}),
(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"})
MATCH p = allShortestPaths((u)-[*1..]->(g))
RETURN p
3. Utilisateurs avec GenericAll sur des groupes privilégiés
MATCH (u:User), (g:Group)
WHERE g.highvalue = true
MATCH p = (u)-[r:GenericAll]->(g)
RETURN u.name, g.name, r.isacl
4. Chercher les ACL abusives (GenericAll, WriteOwner, etc.)
// GenericAll sur un objet
MATCH (u:User)-[r:GenericAll]->(obj)
WHERE NOT obj:Domain
RETURN u.name, type(r), labels(obj), obj.name
// WriteDACL (modification des permissions)
MATCH (u:User)-[r:WriteDacl]->(obj)
RETURN u.name, type(r), labels(obj), obj.name
// WriteOwner (changement de propriétaire)
MATCH (u:User)-[r:WriteOwner]->(obj)
RETURN u.name, type(r), labels(obj), obj.name
// ForceChangePassword
MATCH (u:User)-[r:ForceChangePassword]->(obj:User)
RETURN u.name, obj.name
// AllExtendedRights (souvent inclus DCSync)
MATCH (u:User)-[r:AllExtendedRights]->(obj)
RETURN u.name, type(r), labels(obj), obj.name
5. Sessions actives sur des machines sensibles
// Utilisateurs ayant une session sur un server DA
MATCH (u:User)-[:HasSession]->(c:Computer)
MATCH (c)-[:AdminTo]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"})
RETURN u.name, c.name
// Utilisateurs avec sessions multiples
MATCH (u:User)-[:HasSession]->(c:Computer)
WITH u, count(DISTINCT c) as sessionCount
WHERE sessionCount > 1
RETURN u.name, sessionCount
ORDER BY sessionCount DESC
6. Machines avec contraintes de délégation
MATCH (c:Computer {unconstraineddelegation:true})
RETURN c.name, c.operatingsystem
MATCH (c:Computer)-[:AllowedToDelegate]->(c2:Computer)
RETURN c.name, c2.name
MATCH (c:Computer)-[:AllowedToDelegate]->(c2:Computer)
WHERE c.primarygroupSID =~ "S-1-5-21-.*-512"
RETURN c.name, c2.name
7. Propriétaires des ordinateurs
// Qui peut modifier les propriétés des ordinateurs ?
MATCH (u:User)-[:Owns]->(c:Computer)
RETURN u.name, c.name
8. Groupes locaux administrateurs
// Groupes et utilisateurs qui sont admin local sur plusieurs machines
MATCH (u)-[:AdminTo]->(c:Computer)
WITH u, count(DISTINCT c) as adminCount
WHERE adminCount > 10
RETURN u.name, labels(u), adminCount
ORDER BY adminCount DESC
9. Utilisateurs avec DCSync rights
// DCSync = Replication-Getting-Changes + Replication-Getting-Changes-All
MATCH (u:User)
WHERE u.name =~ "(?i).*admin.*"
MATCH p = (u)-[:DS-Replication-Get-Changes|DS-Replication-Get-Changes-All*1..]->(d:Domain)
RETURN u.name, p
10. Chemins d'attaque GPO
// GPO appliquées à des machines sensibles
MATCH (gpo:GPO)-[:GpLink]->(ou)-[:Contains*1..]->(c:Computer)
MATCH (c)-[:AdminTo]->(g:Group)
WHERE g.highvalue = true
RETURN gpo.name, g.name, c.name
11. Kerberoastable users
// Utilisateurs avec un SPN (Kerberoastable)
MATCH (u:User {hasspn:true})
RETURN u.name, u.displayname, u.title
12. AS-REP Roastable users
// Utilisateurs sans pré-authentification
MATCH (u:User {dontreqpreauth:true})
RETURN u.name
13. Certificates vulnérables (ESC1-ESC8)
// ESC1 : Certificats avec SAN (Subject Alternative Name) non contrôlé
MATCH (n:GPO)-[:GpLink]->(ou:OU)
OPTIONAL MATCH (n)-[:Contains*]->(c:Computer)
RETURN n.name, count(DISTINCT c)
Analyse avancée
Trouver des chemins non documentés
// Chemins > 3 sauts (long mais possible)
MATCH p = shortestPath((u:User)-[*1..10]->(g:Group {name:"DOMAIN ADMINS@DOMAIN.LOCAL"}))
WHERE length(p) > 3
RETURN p
LIMIT 20
Objets avec des permissions non standard
// Objets avec ACL modifiées (potentiellement dangereuses)
MATCH (n)-[r]->(m)
WHERE type(r) IN ["GenericAll", "WriteDacl", "WriteOwner", "ForceChangePassword",
"GenericWrite", "AddMember", "AddSelf", "AllExtendedRights"]
AND NOT n.name =~ ".*DOMAIN USERS.*"
AND NOT m.name =~ ".*DOMAIN ADMINS.*"
RETURN n.name, type(r), labels(m), m.name
Délégation dangereuse
// Délégation d'admin local à des groupes non privilégiés
MATCH (g:Group)-[:AdminTo]->(c:Computer)
MATCH (u:User)-[:MemberOf*1..]->(g)
WHERE NOT g.name =~ "DOMAIN ADMINS@.*|ENTERPRISE ADMINS@.*|BUILTIN.*"
RETURN g.name, count(DISTINCT c) as computers, count(DISTINCT u) as users
ORDER BY computers DESC
BloodHound Custom Queries (JSON)
[
{
"name": "ACL Abuse - GenericAll",
"category": "ACL Abuse",
"query": "MATCH (u:User)-[r:GenericAll]->(obj) WHERE NOT obj:Domain RETURN u.name, type(r), labels(obj), obj.name"
},
{
"name": "Kerberoastable + Description",
"category": "Kerberos",
"query": "MATCH (u:User {hasspn:true}) RETURN u.name, u.description, u.title, u.displayname"
},
{
"name": "High-Value Sessions",
"category": "Sessions",
"query": "MATCH (u:User)-[:HasSession]->(c:Computer) MATCH (c)-[:AdminTo]->(g:Group {highvalue:true}) RETURN u.name, c.name, g.name"
}
]
BloodHound CE (Community Edition)
docker run -d --name neo4j -p 7474:7474 -p 7687:7687 \
-e NEO4J_AUTH=neo4j/bloodhound \
-e NEO4J_PLUGINS='["apoc"]' \
neo4j:5-enterprise
docker run -d --name bhce -p 8080:8080 \
ghcr.io/s0lst1c3/bloodhound-ce:latest
Scénarios complets
1. Audit AD complet
SharpHound.exe -c All
2. Élévation de privilèges via ACL
net group GROUP1 USER /add /domain
3. Kerberoasting guidé par BloodHound
impacket-GetUserSPNs DOMAIN/user:Password@DC -usersfile kerberoast_users.txt
Dépannage
| Problème | Solution |
|---|
| Neo4j ne démarre pas | java --version, vérifier JAVA_HOME |
| "Unable to connect" | Vérifier bolt://localhost:7687 |
| Données vides | Vérifier la collecte (SharpHound.exe -c All) |
| Collecte lente | Réduire les threads (--throttle) |
| Trop de nœuds | Filtrer par type dans la GUI |
| BloodHound CE lourd | Préférer BloodHound original (python) |
Antisèche rapide
SharpHound.exe -c All
bloodhound-python -c All -d DOMAIN -u admin -p Password -dc DC
sudo systemctl start neo4j
bloodhound
MATCH (u:User {hasspn:true}) RETURN u.name
MATCH (n)-[r:GenericAll]->(m) WHERE NOT n:Domain RETURN n.name, labels(m), m.name
MATCH (c:Computer {unconstraineddelegation:true}) RETURN c.name