Conectar OpenCTI+Wazuh+Shuffle+TheHive Parte II (Tendiendo puentes)

Escrito por Jose | Publicado el 29/07/2026 (Actualizado el 22 de September de 2026) | En Redes | 113 lecturas | 11 min de lectura

Foto de Chris Briggs en Unsplash

 

"En la entrega anterior logramos establecer el primer puente directo entre Wazuh y TheHive a través de Shuffle. Sin embargo, ese flujo inicial (Webhook ➔ TheHive) era excesivamente básico: se limitaba a crear casos 'a ciegas', con información escueta y sin ningún tipo de contexto sobre las amenazas.
Un SOC moderno no puede permitirse gestionar alertas en bruto. Necesitamos que cada evento detectado en el kernel venga acompañado de su correspondiente técnica de MITRE ATT&CK, su nivel de severidad y la descripción técnica oficial de OpenCTI.”
En esta segunda parte, vamos a demoler ese primer flujo rudimentario y a construir desde cero un Workflow SOAR enriquecido (SOC_Wazuh_OpenCTI_TheHive_V5). Veremos paso a paso cómo capturar el evento, filtrar las alertas relevantes mediante lógica condicional, consultar la API GraphQL de OpenCTI en tiempo real y moldear el objeto JSON final para que TheHive reciba casos perfectamente estructurados e investigables."

¿Qué teníamos en la Imagen? El punto de partida (El flujo directo y "ciego")

En la imagen vemos la arquitectura inicial que montamos en Shuffle: un flujo compuesto por solo dos elementos conectados en línea recta: `Webhook 1` ➔ `TheHive 1`.

La imagen corresponde al intento de colocar e intentar configurar TheHive como nodo. Como se vio mas tarde se cambio por un Http 1.

¿Cómo funcionaba este esquema inicial?

1. `Webhook 1`: Actuaba como un simple "punto de escucha" (un puerto HTTP expuesto). Cada vez que Wazuh detectaba un evento en el servidor, le disparaba el paquete de datos en bruto (payload JSON) a esta dirección.

2. `TheHive 1`: Usaba la app nativa de TheHive integrada en Shuffle ejecutando la acción `POST Create case`. Recibía los datos tal cual venían del Webhook y creaba un caso en la plataforma.

El problema de este enfoque:

Aunque funcionaba para probar la conectividad, era un sistema inflexible y "ciego":

Información escueta: Creaba casos con títulos genéricos y campos vacíos porque no procesaba el contenido de la alerta.

Sin filtrado: Cualquier evento (incluso alertas de nivel bajo o ruido sin importancia) generaba un caso en TheHive, saturando la plataforma.

Sin inteligencia: No añadía descripciones, no extraía tácticas de MITRE ATT&CK ni consultaba fuentes de inteligencia externa como OpenCTI.

Esta es la captura final del lienzo.

Ahora vamos a ver como crearlo.

Vamos a hacerlo exactamente así, paso a paso, sin prisa y masticando cada nodo para que la documentación sea, sino impecable, si entendible.
La sensación tras un mes de pruebas, cuando un lienzo se vuelve complejo, es de alivio y es que la tentación de tirar la toalla y dejar el SOC como estaba ha sido muy tentadora.

Utilicé las IAs, Copilot, Lovable, Mistral y Gemini Web.

Cada una me ha dado un punto de vista.

Por ejemplo Copilot me puso en la pista de Instalar auditd y crear las reglas en el servidor 2.

Sin eso nada habría sido pasible.

Lovable no me aporto nada.

Mistral me puso en la pista de las condiciones que mas tarde veremos.

Y Gemini Web unió las piezas ¿torpemente?...Uffff!!!! vamos a decir lentamente y a cuenta gotas.

Hasta que después de mil Prueba/Error. Estallo la magia.

Voy a tener que crear un nuevo lienzo para documentar este post. Asi veremos paso a paso el proceso.

Creación del nuevo Workflow en Shuffle
Para construir nuestra orquestación de forma limpia, lo primero que haremos será crear un nuevo flujo de trabajo en la interfaz de Shuffle.
En nuestro panel de Org Workflows, hacemos clic en la opción de crear uno nuevo y le asignamos un nombre descriptivo (en nuestro caso lo llamaremos Doc_Post para esta guía, aunque en nuestro entorno real es la versión SOC_Wazuh_OpenCTI_TheHive_V5). Guardamos los cambios para acceder al lienzo de trabajo.

En esta captura podéis ver mi Workflow ya creado y funcionado. Lo he llamado.

SOC_Wazuh_OpenCTI_TheHive_V5

El Workflow para la documentación lo llamare Doc_Post

Le damos el nombre y salvamos los cambios.

Lo que nos muestra el lienzo ya lo vimos cuando configuramos Wazuh → Shuffle → TheHive.

Limpieza del lienzo: Eliminando el nodo por defecto
Nada más abrir un lienzo en blanco en Shuffle, la plataforma incluye por defecto un disparador genérico etiquetado como Change Me.
Este nodo actúa como un marcador de posición (placeholder) y no nos sirve para la integración con Wazuh. Lo seleccionamos, hacemos clic en el icono de la papelera (Delete) y dejamos el lienzo totalmente despejado para empezar a colocar nuestros propios componentes.

¿Cuál es el siguiente paso exacto en el lienzo?
Ahora que tenemos la mesa limpia, el siguiente paso lógico es traer la primera pieza del puzle:
Ir a la barra lateral izquierda (Triggers).
Arrastrar el nodo Webhook al centro de la pantalla.
Cambiarle el nombre a Webhook 1. Aunque por defecto ya nos da ese nombre.

Si hacemos clic en Webhook 1 se nos abre un cuadro lateral para la configuración del nodo.

Vemos tres cosas importantes:

1.- Nombre del nodo: Por defecto Webhook_1 (o Webhook 1).

"Un detalle fundamental que nos evitará dolores de cabeza al invocar variables más adelante: fijaos en que, aunque en el dibujo del lienzo pone Webhook 1 (con espacio), en la casilla Name de la derecha la plataforma escribe automáticamente Webhook_1 (con guión bajo).
Guardad esto en la memoria: en la sintaxis de las variables dentro del JSON de Shuffle nunca existen los espacios. Siempre referenciaremos la salida de este nodo como $Webhook_1."

2.- Webhook URI: Es la dirección URL única (ej. [http://192.168.1.101:3001/api/v1/hooks/](http://192.168.1.101:3001/api/v1/hooks/)...). La copiaremos como oro en paño para pegarla en la etiqueta <hook_url> del archivo /var/ossec/etc/ossec.conf en nuestro servidor de Wazuh.

Enlazando Shuffle con el Manager de Wazuh
Una vez que hemos copiado la Webhook URI que nos genera Shuffle en la configuración de nuestro nodo, debemos ir a la consola de nuestro servidor Wazuh (soc-server-1) para indicarle a dónde debe disparar las alertas.

sudo nano /var/ossec/etc/ossec.conf

Nos desplazamos al final del archivo, dentro del bloque <ossec_config>, para declarar la integración con Shuffle:

<integration>
  <name>shuffle</name>
  <hook_url>AQUÍ_PEGAS_TU_WEBHOOK_URI</hook_url>
  <level>3</level>
  <alert_format>json</alert_format>
</integration>

Puntos clave de esta configuración:
<name>shuffle</name>: Le indica a Wazuh qué script de integración interno debe ejecutar (Wazuh incluye por defecto el conector para Shuffle en /var/ossec/integrations/custom-shuffle o shuffle).
<hook_url>: Es el puerto de escucha de nuestro SOAR. Aquí pegamos la dirección exacta con su hash/UUID único.
<level>3</level>: Definimos el filtro de entrada. Cualquier alerta registrada en Wazuh con un nivel de severidad 3 o superior activará la llamada hacia Shuffle.
<alert_format>json</alert_format>: Formato estructurado indispensable para que Shuffle pueda parsear los campos en los nodos posteriores.
Importante: Cada vez que modifiquemos este archivo, debemos reiniciar el servicio de Wazuh para aplicar los cambios:

sudo wazuh-control restart

3.- Estado de ejecución (Start / Stop): Inicialmente el nodo aparece como no inicializado (uninitialized). Al pulsar el botón Start, el Webhook se activa y queda en modo escucha listo para recibir los eventos en tiempo real."*

Creando el lienzo.

Este es el mapa mental que vamos a dibujar en la pantalla y la explicación del porqué técnico de esta disposición:

La arquitectura del flujo enriquecido: ¿Por qué esta disposición?
"En este nuevo diseño rompemos el esquema lineal primitivo y montamos una arquitectura en 'árbol' con 5 nodos clave. La razón de estructurarlo así responde a una necesidad lógica muy clara:
Shuffle Tools 1 (El motor de parsing y filtrado):
Recibe el evento directo de Webhook 1. Su función es analizar el JSON, limpiar los caracteres rebeldes y evaluar si el evento contiene una regla de MITRE ATT&CK.
Las dos ramas condicionales (1 condition):
Desde Shuffle Tools 1 creamos dos caminos basados en condiciones:
Rama Izquierda (Http 1): Es el 'camino directo'. Si la alerta NO contiene una técnica MITRE explícita, se envía directamente a TheHive mediante una petición HTTP POST estándar para crear un caso simple.
Rama Derecha (Http 3 ➔ Http 2): Es el 'camino de enriquecimiento con Ciberinteligencia'. Si la alerta SÍ trae una técnica de MITRE (por ejemplo, T1078), se activa esta secuencia de dos pasos.
La secuencia de enriquecimiento (Http 3 ➔ Http 2):
Http 3 (Consulta a OpenCTI): Realiza una llamada GraphQL a la API de OpenCTI buscando la técnica detectada (T1078) para extraer la descripción oficial de la amenaza, tácticas y contexto.
Http 2 (Envío enriquecido a TheHive): Recibe la respuesta de OpenCTI, fusiona la alerta original de Wazuh con la inteligencia recién obtenida y crea en TheHive un caso completo, etiquetado y listo para los analistas.

Desde la parte izquierda vamos seleccionando los diferentes nodos y los arrastramos al lienzo.

Según los vayamos posicionando ellos mismos tomaran el nombre.

¿Cómo se enlazan los nodos en la interfaz de Shuffle?

Al hacer clic o pasar el ratón sobre un nodo (como ves en tu nodo Shuffle Tools 1), aparece un círculo azul en su borde derecho.
Haces clic sobre ese círculo azul, mantienes pulsado y arrastras el cursor hacia el nodo de destino con el que quieras conectarlo.
Al soltar el clic sobre el nodo de destino, se dibuja automáticamente la flecha gris de flujo.

Paso a Paso: Los 4 Enlaces de nuestro Lienzo y su "Porqué"
Enlace 1: De Webhook 1 ➔ Shuffle Tools 1
Cómo conectar: Haz clic en el círculo azul de Webhook 1 y arrastra la línea hasta Shuffle Tools 1.
El porqué: Es el enlace de entrada principal. Webhook 1 recibe el paquete JSON crudo de Wazuh y se lo pasa inmediatamente a Shuffle Tools 1 para que este pueda evaluar la información, limpiar variables y aplicar la lógica del filtro.

Enlace 2: De Shuffle Tools 1 ➔ Http 1 (Camino Estándar)
Cómo conectar: Arrastra una línea desde el círculo azul de Shuffle Tools 1 hacia Http 1.
El porqué: Representa la rama condicional izquierda. Si la alerta de Wazuh NO contiene una técnica de MITRE ATT&CK etiquetada, no hay nada que consultar en OpenCTI. Por tanto, el flujo va directo a Http 1 para crear un caso simple directamente en TheHive.

Enlace 3: De Shuffle Tools 1 ➔ Http 3 (Camino de Inteligencia)
Cómo conectar: Arrastra una línea desde el círculo azul de Shuffle Tools 1 hacia Http 3.
El porqué: Representa la rama condicional derecha. Si la alerta de Wazuh SÍ trae una técnica de MITRE (por ejemplo, T1078), activamos este camino. En lugar de ir directo a TheHive, el flujo salta a Http 3 para realizar una consulta GraphQL a la API de OpenCTI y pedir la descripción e inteligencia asociada a esa amenaza.

Enlace 4: De Http 3 ➔ Http 2 (Pase de Testigo y Enriquecimiento)
Cómo conectar: Arrastra una línea desde el círculo azul de Http 3 hacia Http 2.
El porqué: Este enlace es vital porque establece la secuencia temporal de la rama derecha. Http 2 es el nodo que envía la alerta a TheHive, pero no puede ejecutarse antes de que Http 3 haya terminado de hablar con OpenCTI. Al conectarlos en serie (Http 3 ➔ Http 2), garantizamos que Http 2 reciba tanto la alerta de Wazuh como la respuesta rica de OpenCTI para enviársela masticada a TheHive.

Esta ultima imagen seria el resumen de lo que acabamos de hacer.

La lógica de decisión: Bifurcaciones condicionales en el lienzo
Echando un vistazo al mapa completo de nuestro Workflow, podemos observar cómo las líneas que nacen en Shuffle Tools 1 se dividen hacia dos destinos diferentes (Http 1 a la izquierda y Http 3 a la derecha).
En Shuffle, estas flechas de enlace no son meros tubos pasivos por los que viajan los datos; son puertas lógicas condicionales.
Si hacemos clic directamente sobre cualquiera de los enlaces que salen de Shuffle Tools 1, se abrirá un panel lateral derecho dedicado exclusivamente a la configuración de condiciones (Conditions):

Vemos que si vamos a New condition se vuelve a abrir un cuadro de dialogo donde configuraremos esa condición que iría desde Shuffle Tools 1 a Http3. Lo mismo haríamos desde Shuffle Tools 1 a Http 1
¿Cómo funciona un enlace condicional?
Nos permite evaluar el contenido de la alerta en tiempo real. Podemos indicarle a Shuffle reglas del tipo: "Solo si el campo X es igual a Y, permite que el flujo continúe por este camino".
Nuestra lógica de filtrado:
Línea hacia Http 1: Se configurará con una condición que se cumpla cuando la alerta de Wazuh NO contenga referencias a técnicas MITRE ATT&CK (enviando el evento crudo a TheHive).
Línea hacia Http 3: Se configurará con la condición opuesta; es decir, cuando la alerta SÍ contenga un ID de MITRE (como T1078), desviando el tráfico hacia OpenCTI para enriquecer el caso.
Con esta arquitectura totalmente planteada en el lienzo y comprendida la función de cada nodo, cerramos el diseño estructural del SOAR. En el siguiente bloque nos meteremos 'hasta la cocina' de cada uno de los nodos para configurar sus tokens de autenticación, URLs, expresiones regulares y consultas GraphQL.


 

Barakaldo 28 de julio de 2026


 

 

 

 

 

 

0 Votos
¿Te gustó el artículo? ¡Compártelo!

Etiquetas:

SOC
Jose

Sobre Jose

Este autor prefiere mantener el misterio y aún no ha escrito su biografía.

Comentarios (0)

Inicia sesión para unirte a la conversación.

No hay comentarios aún. ¡Sé el primero en comentar!