Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
Kestra-cve-2026-53576 — Reproducción de extremo a extremo y detección multicapa de CVE-2026-53576, el RCE no autenticado en Kestra — llevado más allá del PoC base para mostrar cómo una mala configuración común del socket de Docker convierte el root del contenedor en un compromiso total del host. | Kitploit
Herramientas/GitHubGitHub/atlasvector/kestra-cve-2026-53576
Escalada de PrivilegiosSeguridad de ContenedoresMecanismos de PersistenciaAnálisis de VulnerabilidadesExplotaciónPost-ExplotaciónPruebas de PenetraciónPapers e Investigación

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir
Red Teaming
Respuesta a Incidentes
Labs y Práctica
GitHubatlasvector/kestra-cve-2026-53576

Kestra-cve-2026-53576

Reproducción de extremo a extremo y detección multicapa de CVE-2026-53576, el RCE no autenticado en Kestra — llevado más allá del PoC base para mostrar cómo una mala configuración común del socket de Docker convierte el root del contenedor en un compromiso total del host.

Ver Repositorio
hace 2 díasAún no revisado

RCE no autenticada en Kestra mediante un bypass de autenticación por ruta final (CVE-2026-53576)

Contenido

  • Resumen ejecutivo
  • 1. Resumen
  • 2. Versiones afectadas / corregidas
  • 3. Entorno de pruebas y verificación previa
  • 4. Causa raíz
  • 5. Simulación del ataque
  • 6. Ingeniería de detección
  • 7. Mapeo ATT&CK
  • 8. Remediación y endurecimiento
  • 9. Referencias

Resumen ejecutivo

Kestra, una plataforma de orquestación de flujos de trabajo de código abierto, distribuyó un filtro de autenticación que decidía si una solicitud necesitaba credenciales comprobando si la URL terminaba con /configs - una comprobación destinada a exponer un único endpoint público inofensivo.

Debido a que la comprobación solo miraba el final de la cadena, cualquier solicitud cuya URL terminara de esa forma omitía por completo la autenticación, incluidos los endpoints que crean y ejecutan código arbitrario. El resultado: cualquiera que pueda alcanzar una instancia vulnerable de Kestra a través de la red puede ejecutar comandos como root sin credenciales, sin phishing, sin adivinar contraseñas y sin necesidad de ningún paso de escalada de privilegios.

En este ejercicio, esa única brecha se llevó de principio a fin contra una instancia de laboratorio autoalojada:

  • Ejecución de código no autenticada.
  • Descubrimiento de un socket de Docker expuesto.
  • Escalada a acceso root completo en el host subyacente.
  • Dos mecanismos de persistencia independientes (una clave SSH de puerta trasera y un beacon programado).

Cada etapa se capturó contra telemetría defensiva (IDS de red, seguridad en tiempo de ejecución del host, auditoría de Linux y registros del sistema).

Impacto empresarial si no se parchea: compromiso total del host que ejecuta Kestra, no solo de la aplicación, y por extensión de cualquier otra cosa alcanzable desde ese host.

Solución: actualizar a Kestra 1.0.45 / 1.3.21 o posterior (el parche por sí solo cierra la vulnerabilidad principal; las etapas de escalada y persistencia requieren una corrección separada e independiente: no montar el socket de Docker en contenedores de aplicaciones, véase la Sección 8).

1. Resumen

Este informe documenta CVE-2026-53576, una vulnerabilidad de ejecución remota de código no autenticada con CVSS 10.0 en Kestra ≤1.3.20, causada por un bypass de autenticación por sufijo de ruta (AuthenticationFilter.java, endsWith("/configs")).

Un atacante que nombre el namespace y el ID de un flujo de trabajo como configs puede crear y ejecutar comandos de shell arbitrarios sin credenciales, como root, dentro del contenedor de Kestra. Corregido en 1.0.45 y 1.3.21. El mismo fallo también se reportó de forma independiente bajo CVE-2026-49869, que es el número incluido en el catálogo KEV de CISA vinculado a explotación real en el mundo real. Ambos deben citarse juntos, ya que las fuentes públicas y los escáneres pueden hacer referencia a cualquiera de los dos.

2. Versiones afectadas / corregidas

VulnerableKestra ≤ 1.3.20 (y anteriores a 1.0.45 en la línea 1.0.x)
Corregida1.0.45 / 1.3.21+
CVECVE-2026-53576
Aviso gemeloCVE-2026-49869 - mismo fallo, incluido en KEV de CISA (en el mundo real)

Cronología

FechaEvento
2026-06-02Se publica Kestra 1.3.21; el changelog menciona un "posible bypass de autenticación en el filtro de autenticación"
2026-06-03Se publica Kestra 1.0.45 en la línea 1.0.x
2026-09-02CVE-2026-49869 (el aviso gemelo) se añade al catálogo KEV de CISA

3. Entorno de pruebas y verificación previa

Homelab autoalojado: - Host Debian (nombre de host docker, kernel 6.12.107+deb13-amd64), - Docker Engine 29.8.1. - Kestra desplegado como la imagen oficial kestra/kestra:v1.3.20, accesible a través de un proxy inverso Caddy en kestra.int.atlasvec.com. - Pila de telemetría bajo prueba: Falco (runtime/eBPF, a nivel de host), - Suricata 8.0.3 IDS (espejo SPAN pasivo), reenviando hacia Splunk.

Antes de tocar nada, confirmé que el objetivo era realmente vulnerable y que la pila de telemetría estaba activa. También tomé una instantánea del estado previo al ataque para poder revertir una vez terminado.

Kestra ejecutando la versión vulnerable: 01-kestra-version-v1.3.20

El propio contenedor, activo y accesible: 06-docker-kestra-running

Las unidades de Falco cargadas en el host: 02-falco-units-one-active

Falco emitiendo eventos activamente (modo eBPF moderno): 03-falco-modern-bpf-active-emitting

El servicio de Suricata activo: 04-suricata-systemctl-active

Y su eve.json escribiendo eventos en vivo: 05-suricata-eve-json-live

4. Causa raíz

Aquí se alinean dos errores, no uno.

En primer lugar, el filtro de autenticación decide si una solicitud puede omitir la autenticación haciendo coincidir el final de la ruta de la solicitud:```java // AuthenticationFilter.java — the vulnerable check, confirmed against the self-hosted v1.3.20 source if (path.endsWith("/configs")) { // treated as a public, unauthenticated path }

root@kitploit:~
Esa comprobación existe para exponer un único endpoint inofensivo, la configuración de la instancia pública. Como `endsWith` solo lee la cola de la cadena, no puede distinguir una ruta segura de cualquier otra ruta que termine de la misma manera.

En segundo lugar, el enrutador de Kestra sigue enviando esas rutas similares a sus manejadores reales y sensibles. `/api/v1/main/flows/configs` llega al manejador de creación de flujos. `/api/v1/main/executions/configs/configs` llega al manejador de ejecuciones. El filtro deja pasar ambas como públicas, y el enrutador las ejecuta de todos modos. Nombra el namespace y el ID de un flujo como `configs`, y un endpoint que ejecuta código ahora termina en `/configs`, por lo que hereda el pase libre de la ruta pública.

El par de solicitudes capturado lo muestra claramente. `GET /api/v1/main/flows/search` sin credenciales devuelve `401`. `POST /api/v1/main/flows/configs` con el mismo encabezado de autenticación vacío devuelve `200` y almacena el flujo (ver §5.1).

## 5. Simulación de ataque

> Cada paso a continuación está capturado con su propia captura de pantalla. Todo se ejecuta dentro de mi propio homelab aislado contra una instancia de Kestra autoalojada detrás del proxy inverso.

### 5.1 Etapa 1 - bypass de autenticación -> root dentro del contenedor de Kestra

**Control :** `GET /api/v1/main/flows/search` sin credenciales → `401 Unauthorized`. 
Confirma que la autenticación se aplica en una ruta normal.
![01-burp-control-401](https://assets.kitploit.com/production/public/readmes/56348/2a6d266e96b2b4e09bc32c0ccf3609159eaf5bacdc204989d5572211e616e6ff/8a8bab993fd7ba08656d03ad85822001996be4c391de87c535751cc9e14542a1-display-v1.webp)
_____

**Plant :** Enviando `POST /api/v1/main/flows/configs` sin encabezado de autenticación. El cuerpo es un YAML de flujo cuyo `namespace` y `flow id` son ambos `configs`, y contiene una tarea Commands que usa el task runner Process. El servidor devuelve `200 OK` y almacena el flujo. El sufijo `/configs` en una ruta por lo demás protegida es lo que desencadena el bypass **(ver Sección 4).**
![02-burp-plant-flow-200](https://assets.kitploit.com/production/public/readmes/56348/5d2a2db2d70e9d60e7136c765a7a85f4d8b684ea945da5b84e84d85a2b05a151/1ee6d8f7efd58d22ef41b536f32acbbdd417d68ac030ed28e2d06f9d6d4ccb93-display-v1.webp)
**Listen & Wait** : Iniciando un listener simple usando nc con fines de prueba, para capturar la reverse shell.

![03-kali-listener-4444](https://assets.kitploit.com/production/public/readmes/56348/88d7d3516aaeef900bbb9b372d9006323a3d7391078b693124ee24710da557ac/aa9806454d3742b7e958611a5c6ed2d3dfb3072eec3c14e4bb3f050a41220803-display-v1.webp)




**Trigger / Execution** `POST /api/v1/main/executions/configs/configs`, sin encabezado de autenticación → `200 OK`, nueva ejecución creada.
![04-burp-execute-200](https://assets.kitploit.com/production/public/readmes/56348/e70d1cd38f3825dca36c25e722bdfcf4a7614b1402fe1b6d0ccebdf992738bbe/9a394373a293d22ef55e3b6ee32eae6991feac73a5ccbc7909536bdf3435172d-display-v1.webp)

**BaaaaM :** Hemos obtenido la shell, pero recuerda - estamos "aislados", `root` **PERO** dentro del contenedor Docker de Kestra, así que "no deberíamos" poder escapar de aquí. "**bueno, eso es lo que pensaba**"
![05-kali-revshell-container](https://assets.kitploit.com/production/public/readmes/56348/97257430abd2415f37f12c790a738d73e12f0c2509c193b1b7d24545453a1a70/9880399e445d4b8b602c1f381bbd8523a83c8c3c097b9a919e2b1871c7f1129e-display-v1.webp)


El comando de la tarea se ejecuta como hijo directo del proceso JVM de Kestra, confirmado mediante el árbol de procesos del lado del host, y se completa con éxito según el propio registro de ejecución de Kestra.

**Panel de registros de Kestra**
![06-kestra-ui-pwn-log](https://assets.kitploit.com/production/public/readmes/56348/b447d0d268daa119b1d64a9d7d95a588b80a7cb228613b81a6bfd69777aea7bb/467a61936f8779b533cc83a297d651957e17f9d00241ff97cc7640df917450fe-display-v1.webp)


**Árbol de procesos de Kestra**
![07-kestra-process-tree](https://assets.kitploit.com/production/public/readmes/56348/a7e20df484e1c5759fca4f5e403bc280ffc45b03b47dae22804321bb8398858c/0a0e30aa6c0537adf8ddd204453c8d51e808de2d5ff764fc5ad8f551cf059665-display-v1.webp)

**Resultado:** ejecución remota de código no autenticada como root, dentro del contenedor de Kestra. Esta es la prueba completa y autocontenida de **CVE-2026-53576**.


### 5.2 Etapa 2 - escalada mediante socket de Docker expuesto (específico del homelab, no forma parte del propio CVE)

Desde la shell de la Etapa 1, se encontró `/var/run/docker.sock` montado en el contenedor - un patrón Docker-outside-of-Docker (DooD), común cuando el propio task runner `Docker` de Kestra está configurado, ya que necesita un daemon con el que comunicarse. 

Alcanzar ese socket es equivalente a **root** en el host: la API de Docker permite a un cliente configurar montajes bind arbitrarios del host y namespaces de PID/red del host para los contenedores que genera, y el daemon detrás del socket ya se ejecuta como root en el host. 

Esto no es un exploit de kernel ni de escape de contenedor - es la API de Docker haciendo lo que está diseñada para hacer, alcanzada desde un lugar desde el que no debería haber sido alcanzable.

Usando el socket, creé un contenedor hermano con el sistema de archivos del host montado y los namespaces de PID y red del host, y luego lo inicié.

**Nota:** una segunda variante más silenciosa también surgió durante las pruebas, aunque no la capturé por separado. En lugar de crear siempre un nuevo contenedor hermano, el mismo acceso al socket te permite ejecutar `POST /containers/{id}/exec` contra un contenedor que ya está en ejecución, por lo que no hay ningún evento de creación de contenedor. En este host Docker tengo tanto Kestra como Portainer, cualquiera de los cuales podría usar para el mismo escape. Eso importa para la detección: cualquier regla centrada en la creación de un nuevo contenedor privilegiado pasa por alto esta variante.

Confirmando root y encontrando el socket ahí, sin restricción alguna:
![08-docker-socket-present](https://assets.kitploit.com/production/public/readmes/56348/d2a34fd7db05bb2966a540410dbc8e76cfec416a545786349372984902b128f9/ca3ce180476010ee482b60c42687751f27a072aa2c0b78fbb6400b8406cee5e5-display-v1.webp)

Comprobando que el daemon de Docker es realmente accesible a través del socket:
![09-docker-api-version](https://assets.kitploit.com/production/public/readmes/56348/7ce4365a9c48db827aa3c6e53c73622bef0ee7a99f530b5e37a065601b3892b0/d6debd41ca945cd5812add55df46cc5dd2f7bbaba1c88965f438ee7d5c9a4bcc-display-v1.webp)

Listando qué imágenes ya están locales, para no necesitar descargar nada:
![10-docker-images-enum](https://assets.kitploit.com/production/public/readmes/56348/aa1ff3ff76e92437899afc7b603925eeb53838f99f4d8586df69f8a96ff23622/34cd26942854c4c4bf59135beb54cac278aaad304faac4a3f5b64bec9e1a84de-display-v1.webp)

Primer intento: un contenedor privilegiado con el sistema de archivos del host montado:
![11-docker-create-privileged](https://assets.kitploit.com/production/public/readmes/56348/38f4f42a486e3f46f4d798e131b3eb3bd58a7e7507b7a9e88845ed52ee32bd29/673b8ab3de93e21c6fbe23b343c4cd7fc4ddac11554ad56c0d656e2ae46467dd-display-v1.webp)

Segundo intento, esta vez añadiendo los namespaces de PID y red del host:
![12-docker-create-hostns](https://assets.kitploit.com/production/public/readmes/56348/f2a5c239adbabc9b3cef7f24d2ff60b49765bfec2ec231520d18edbcaec597cb/c387405779506f4d5e8f30715d359550b69d2c1a899525b293e8b69ce61c6e73-display-v1.webp)

Tercer intento, haciendo chroot directamente en el sistema de archivos del host montado:
![13-docker-create-chroot](https://assets.kitploit.com/production/public/readmes/56348/dc38f66a291764a224f2982d22b9ca3cb37bdb31d39c48344b8030448f452e41/23519a1a158885f8b9b5691ffab18ef6eb1b5c989af00bf7c4caf6fe58ee7176-display-v1.webp)

Listener activo y esperando en el puerto al que llamará la shell de escape:
![14-host-listener-4491](https://assets.kitploit.com/production/public/readmes/56348/37b558192ffff02366b4d219e2393d1f9fe468e82555c90a236e2cf1bdd35aa7/116c772ff659ec661cad22e023a6179eb8ffd1ebf409624b4832a27a4e947626-display-v1.webp)

Iniciando el contenedor:
![15-docker-container-start](https://assets.kitploit.com/production/public/readmes/56348/277f7899c2fbb23d86a1918621f5efe79c635bd84af584811e98bdf37b7ab253/3f02d6a19613662df1b32fb8fa1bdbb03043f6b232844d2de3a23f552873103e-display-v1.webp)


**Root, pero esta vez es el host, no el contenedor:**
![16-host-root-id](https://assets.kitploit.com/production/public/readmes/56348/0a77d4e6c239354c2c79737c51f492005cf129af8c5a595614c1005c0a125405/02ed259073555446cd67e2ce2ab86c7408fb9c2e7864ce3daac8bc50fbd2db36-display-v1.webp)

Versión del kernel que coincide con el host real, no con la vista aislada de un contenedor:
![17-host-root-uname](https://assets.kitploit.com/production/public/readmes/56348/9f059686a831bfb8b5196412b9fd10492e8aeeb211dcb7d45fc98b3b6c0f999c/2c2dbd97e8c41b21085d9230d3b2ffb74f76c693947d9831007cff197fe3647d-display-v1.webp)


Actualizando a una shell interactiva adecuada para el resto de la sesión:
![18-host-pty-upgrade](https://assets.kitploit.com/production/public/readmes/56348/34894e77c38df22cbbd807a14fd14b8e49aadc6f894d990e4022bc5b85978b62/0f81e4ed6fa6dfef8867eed194e7e4cdf12dc025b00c5763b2884530199c15d7-display-v1.webp)

### 5.3 Etapa 3 - persistencia, confirmada en ejecución

Desde la shell con root en el host configuré dos mecanismos de persistencia independientes, 

**Primero**, una clave SSH. Comprobé quién ya tenía acceso :
![19-host-authkeys-enum](https://assets.kitploit.com/production/public/readmes/56348/553f3a2b399361ce652e836fab2525686519f44dee9d94d8b7c9d45b1b939d44/0a2c697dc0f216566dba1b4cb38f134ce23ff7b57bc40dc87032016a558e2668-display-v1.webp)

Luego revisé la propia configuración de sshd por si algo bloquearía una nueva clave:
![20-host-sshd-config-enum](https://assets.kitploit.com/production/public/readmes/56348/a25dd7b5a8376e48cee6c75e64264fa973def1db09a9d7ea520b705e32021ef3/adbfee0a5f27442b43fa318a36ef281d5abc1d998c367f2e5978b11d8282677d-display-v1.webp)

Generé un par de claves en la máquina atacante:
![21-attacker-keygen](https://assets.kitploit.com/production/public/readmes/56348/4b560189f5ab37c619d941dfedadd77a4fa8a49420aa720eafd6fccc44f7f734/f90cf5f5b1ebb76fe1505b063ef844e17c9c7b8e9f21a2f92213eb36f9428dec-display-v1.webp)

Confirmé que sshd estaba realmente escuchando:
![22-host-sshd-active](https://assets.kitploit.com/production/public/readmes/56348/bd0ee4ae0a24f08b096c16eff66fd4ff87efccd92f1c1b509078d24f65af0e0f/78518194b025287cdf07b81a3335ea8b02239fcca6cbd2f32b507e28cc908cf9-display-v1.webp)

Coloqué la clave pública en el `authorized_keys` de root:
![23-host-authkeys-implant](https://assets.kitploit.com/production/public/readmes/56348/e2faba217e62433f6dcd9777fa85c8dcd24858ab1c6a2f5d1293515d744003bc/0c1ca3973a85e0ade63514eaa9ad4f3d0fd63f047dc7be19b112058f24632cfd-display-v1.webp)

Y accedí con la clave privada correspondiente:
![24-ssh-root-login-proof](https://assets.kitploit.com/production/public/readmes/56348/14b698fb9eae32aff09e6ec7d179ecf1c2ef665d7b87be8d6f9fac956e68db2b/a2ced84629d34de099a598e38f71ba54411a890eaadb50a2dc8dd8dc099a6459-display-v1.webp)

**PD:** Eso es acceso root independiente de la cadena de RCE original. Aunque Kestra se parchee, esta clave sigue funcionando.

**Segundo**, un beacon de cron. Coloqué una llamada de retorno a nivel de root programada para ejecutarse a intervalos, y luego probé con un listener nuevo para ver si realmente se disparaba según lo previsto:
![25-host-cron-persist](https://assets.kitploit.com/production/public/readmes/56348/3dfa92072c55dd052127ef69943a6c43a855534420b286e0dbd62ce833dc441f/7a75828de1e323b44a4c792a2eed2713cf656433685deef7931026f815b2dd98-display-v1.webp)

**Se disparó. Un segundo punto de apoyo en el host, independiente tanto del RCE como de la clave SSH.**


### 5.4 Cronología verificada de la kill-chain.

La cronología a continuación es diferente: está reconstruida enteramente a partir de telemetría independiente del lado del defensor (IDS de red + seguridad en tiempo de ejecución del host), extraída y validada en vivo contra datos reales de Splunk.

**RCE principal - la red detecta la entrega, el host confirma la ejecución, con 103 segundos de diferencia:**

| Hora (EDT)   | Capa               | Evento                                                                                        |
| ------------ | ------------------ | -------------------------------------------------------------------------------------------- |
| 02:46:09.778 | Red (Suricata)     | Se dispara la firma pública ET para este CVE exacto                                          |
| 02:47:52.277 | Host (Falco)       | Reverse shell confirmada dentro del contenedor de Kestra, con el comando exacto y el ID del contenedor capturados |

**Escalada - la red y el host corroboran cada uno de forma independiente una parte distinta del mismo evento:**

| Hora (EDT)   | Capa               | Evento                                                                                                                              |
| ------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| 03:48:55.503 | Host (Falco)       | Reverse shell desde el contenedor de escalada                                                                                      |
| 03:51:57.360 | Red (Suricata)     | Flujo TCP **y** una alerta basada en contenido - la cadena literal `uid=0(root)` se vio saliendo del host en texto plano cuando se ejecutó `id` |


## 6. Ingeniería de detección

Construí las detecciones contra telemetría real capturada, y luego probé cada una contra una repetición. La matriz muestra dónde existía cobertura antes de empezar y dónde no.

### 6.0 Matriz de cobertura de detección

| Etapa | Red (Suricata) | Host (Falco) | Host (auditd/journald) | Estado |
| --- | --- | --- | --- | --- |
| Solicitud de exploit inicial | Se dispara la firma pública ET | Sin visibilidad de capa de aplicación | - | Cubierto (preexistente) |
| Ejecución de RCE | - | Regla nativa, etiquetada T1059 | - | Cubierto (preexistente) |
| Escalada por socket de Docker (la técnica) | - | Brecha: solo captura la shell resultante, no las llamadas a la API de abuso del socket | Los registros EXECVE capturan las llamadas exactas `curl --unix-socket` | Brecha encontrada, cerrada con auditd + una regla Falco personalizada |
| Confirmación del impacto de la escalada | Alerta de contenido sobre la salida filtrada de `id` | La misma regla genérica de shell | - | Cubierto (preexistente, entre capas) |
| Persistencia por SSH | - | - | journald: ciclo de vida completo de PAM más la huella de la clave | Cubierto (solo host) |
| Persistencia por cron | - | - | journald y linux_audit, dos fuentes, cadencia exacta de 5 min | Cubierto (solo host) |

La brecha es la escalada por socket de Docker. Las reglas predeterminadas de Falco capturan la shell que genera un contenedor comprometido, pero nada en el conjunto predeterminado estable marca un proceso que alcanza `/var/run/docker.sock` para manejar directamente la API de Docker. Las reglas que tocarían lanzamientos de contenedores privilegiados, `Launch Privileged Container` y `Launch Sensitive Mount Container`, se distribuyen con madurez `incubating` y `sandbox`, por lo que el conjunto de reglas predeterminado tampoco las carga. Cerré la brecha con una búsqueda de correlación de auditd (Detección 03) y una regla Falco personalizada (§6.3).

### 6.1 Splunk - cinco búsquedas de correlación, desplegadas y programadas

Las cinco se ejecutan en vivo en Splunk (`*/5 * * * *`, seguimiento de alertas habilitado, limitación por campo), no solo escritas y dejadas como texto. El SPL completo, las notas exactas de FP, la severidad, las etiquetas MITRE y los runbooks de respuesta para cada una están en `detections/splunk/*.spl`. La tabla de estado a continuación es el resultado probado en vivo para cada una, incluido un bug real que encontré y corregí.

| #   | Detección                                                  | MITRE                | Estado                                                                                                                              |
| --- | ---------------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| 01  | Firma de exploit de red (consume la alerta ET de Suricata) | T1190                | **Disparada** - repetición histórica confirmada, sin nuevos eventos desde entonces (fuera del lookback actual)                                             |
| 02  | Ejecución de RCE en host (regla Falco de redirección a red)        | T1059                | **Disparada** - repetición histórica confirmada                                                                                             |
| 03  | Abuso de socket de Docker (auditd, la que cierra la brecha)               | T1610, T1611         | **Disparada en el propio programador en vivo** - `triggered_alert_count: 1` confirmado en la ejecución real `*/5 * * * *`, no solo en una prueba manual |
| 04  | Persistencia de inicio de sesión root por SSH                                 | T1098.004, T1021.004 | **Disparada** - repetición histórica confirmada                                                                                             |
| 05  | Persistencia por beacon de cron                                    | T1053.003            | **Desplegada con un bug que encontré y corregí en vivo.** La ventana de despacho `-10m` contenía solo dos de los tres intervalos de 5 minutos que necesita el umbral `distinct_intervals >= 3`, por lo que nunca podía dispararse a pesar de que el beacon seguía ejecutándose en datos reales. La amplié a `-30m` y la redesplegué - y el programador la ha disparado 53 veces desde entonces, así que la corrección se mantiene. |

La división del trabajo de la Detección 03 es deliberada: en lugar de reimplementar la propia lógica de firma de Suricata en SPL, o intentar que Falco capture una técnica a nivel de socket para la que no fue construido, la capa SIEM aquí consume el registro EXECVE de auditd de las llamadas exactas `curl --unix-socket` - la fuente de telemetría que se demostró más fiable para esta técnica específica.

1. **Detección 01** - Disparo de la firma ET (alerta `suricata:eve`):```spl
index=main sourcetype=suricata:eve event_type=alert
  alert.signature="ET WEB_SPECIFIC_APPS Kestra Unauthenticated Remote Code Execution (CVE-2026-53576)"
| stats count min(_time) as first_seen max(_time) as last_seen
        values(src_ip) as source_ips
  by dest_ip dest_port
| eval first_seen=strftime(first_seen,"%Y-%m-%d %H:%M:%S")
| eval last_seen=strftime(last_seen,"%Y-%m-%d %H:%M:%S")

det01-network-et-signature

  1. Detección 02 - la regla de redirección a red de Falco, desglosada por contenedor. La IP de origen cambia de la dirección de bridge del contenedor de Kestra (172.17.0.3, RCE principal en el puerto 4489) al propio host (172.66.66.67, escalada en el puerto 4491) - la escalada de contenedor a host hecha visible - mientras que el destino permanece constante: el listener del atacante en 172.66.66.125: det02-falco-redirect-revshell

  2. Detección 03 - registros EXECVE de auditd de curl --unix-socket docker.sock: det03-auditd-docker-sock

  3. Detección 04 - inicio de sesión SSH de root en journald, huella de clave capturada: det04-ssh-root-login

  4. Detección 05 - el beacon cron de archivo oculto con punto (/usr/local/bin/.sysmon) ejecutándose como root con una cadencia exacta de 5 minutos: 79 intervalos distintos a lo largo de ~6,5 horas (04:30-11:00 EDT). El umbral distinct_intervals >= 3 es lo que separa un beacon periódico de un trabajo cron puntual: det05-cron-beacon

Las cinco desplegadas como búsquedas guardadas programadas (*/5 * * * *): saved-searches-scheduled

Prueba de que el programador de cron realmente las ejecuta, no solo de que existen: las cinco se ejecutaron 54 veces. La Detección 03 se disparó una vez (el abuso del docker-socket, 06:35 EDT) y la Detección 05 se disparó 53 veces (el beacon cron aún activo). Las Detecciones 01/02/04 muestran 0 disparos, ya que son eventos históricos puntuales (solicitud de exploit, RCE, inicio de sesión SSH) que han quedado fuera de la ventana de búsqueda de -10m, mientras que una instancia activa o recurrente seguiría alertando: scheduler-triggered-alert

6.2 Sigma - regla portátil de spawn de procesos en host

El patrón de reverse-shell /dev/tcp/ - usado tanto en el RCE principal como en el callback de escalada. SigmaHQ incluye una regla para ello: "Suspicious Reverse Shell Command Line" (id 738d9bcf-6999-4fdb-b4ac-3033037db8ab, de Florian Roth en Nextron Systems), y una de sus palabras clave es bash -i >& /dev/tcp/ - exactamente lo que apareció en nuestra captura.

Así que tomé esa regla sin cambios (detections/sigma/lnx_shell_susp_rev_shells.yml) y verifiqué su palabra clave contra el mismo evento de Falco que la Detección 02 ya había capturado. Sigma no "se dispara" por sí sola - es una firma portátil, no un motor en ejecución - pero puedo mostrar su palabra clave incidiendo sobre telemetría real de esta ejecución en lugar de un ejemplo de manual.

Regla pública de SigmaHQ "Suspicious Reverse Shell Command Line" - su palabra clave bash -i >& /dev/tcp/ contra el mismo evento real que la Detección 02:

sigma-devtcp-match-event

6.3 Falco - regla personalizada que cierra la brecha del docker-socket

detections/falco/docker_socket_abuse.yaml - desplegada en la instancia activa de Falco y confirmada disparándose en una repetición real, 2026-09-24T10:27:29Z.

El conjunto de reglas predeterminado de Falco no cubre esto. Detectar un proceso que accede a /var/run/docker.sock no es una idea nueva - los propios ejemplos de Falco de Sysdig lo hacen vigilando open_write sobre la ruta del socket - pero no existe tal regla en el conjunto incluido/predeterminado (el proyecto tiene una solicitud abierta para una, falcosecurity/falco #2940), y la única regla predeterminada adyacente solo captura los CLI docker/kubectl, no un curl --unix-socket en crudo.

El problema: ese enfoque estándar de open_write sobre el socket no se disparó en esta configuración - con modern_bpf y un espejo pasivo, se accede al socket mediante connect(), no open(). Así que en su lugar hago coincidir la línea de comandos del proceso en el momento del spawn (spawned_process + proc.cmdline contains "docker.sock"), la misma clase de evento que Falco ya maneja de forma fiable aquí. Se dispara dos veces por llamada - el wrapper de shell y la hoja curl - con contexto completo:``` priority=Critical, container_id=d417e027d444, image=kestra/kestra:v1.3.20, user=root, cmdline="curl -s --unix-socket /var/run/docker.sock http://localhost/version", tags=[T1610, T1611]

root@kitploit:~
Regla personalizada de Falco disparada - "Unexpected Process Accessing Docker Socket" (T1610/T1611):
![det17-falco-custom-docker-sock](https://assets.kitploit.com/production/public/readmes/56348/6fa1b11a7c8c6a3c8619ac95a2950cf1f326df0ef1651324aa0b4f80db389a12/8ac8f1a2c5184a84ba2af0c9c85c3112506e19c62b0734105e5b74c90e4d8078-display-v1.webp)

Reglas de Falco estándar que se dispararon - el conjunto por defecto no tiene una regla para el socket de Docker, que es la brecha:
![falco-rule-inventory](https://assets.kitploit.com/production/public/readmes/56348/5da667ac881b32f6bc633e58b4d00a08ea22cf3a5000b3ae8522cb3937b051a4/3fe1201158632dc6aef5257bf3620e83e087814f3da0108f7d2ef04fd5088ec9-display-v1.webp)

### 6.4 Suricata - cobertura pública existente, regla personalizada diferida

La capa de red para el exploit principal ya está cubierta por una firma pública de Emerging Threats, `ET WEB_SPECIFIC_APPS Kestra Unauthenticated Remote Code Execution (CVE-2026-53576)`, que se disparó sobre tráfico real durante la Fase 2.

A continuación se muestra el mismo bypass visto en la capa de red, y construí la consulta a partir del patrón de la vulnerabilidad. Cada petición cuya ruta terminaba en `/configs` sobre un endpoint `flows` o `executions` devolvió `200`, mientras que una ruta normal (`/flows/search`) devolvió el `401` esperado.

La columna `Attacker IP (XFF)` es el origen HTTP real, leído del encabezado `X-Forwarded-For`: `10.10.10.106`, mi Mac ejecutando Burp. El propio `src_ip` de Suricata solo ve el salto del proxy inverso (`172.66.66.1`). Esa es una máquina distinta de la caja Kali `172.66.66.125` que después recibió las reverse shells e hizo el inicio de sesión SSH, por lo que el exploit HTTP y los callbacks provinieron de hosts separados.

![suricata-raw-post-http](https://assets.kitploit.com/production/public/readmes/56348/d713d35f0d858af8dd5d477a9929ed6d07e55bce5e9e43946dfe1fb1cca73699/975155c6fe8a39a0de715497a7e5a659b17641a7ed4ed2d7f4d7bfcd02842398-display-v1.webp)

### 6.5 Dashboard

`cve_2026_53576_kill_chain` está desplegado en Splunk y contiene: KPIs destacados (capas de detección, técnicas de ATT&CK, detecciones desplegadas, mecanismos de persistencia), un gráfico de columnas de la línea de tiempo del ataque coloreado por capa de telemetría, un mapa de la kill-chain de MITRE ATT&CK con un recuento de evidencia en vivo por etapa, la línea de tiempo correlacionada de red y host de la §5.4, la cobertura de detección por búsqueda guardada programada, el desglose de la técnica del socket de Docker, y una tabla de indicadores de compromiso extraída en vivo de los logs.

- KPIs, el gráfico de la línea de tiempo del ataque, y el inicio del mapa de ATT&CK:
![dashboard-kill-chain-1](https://assets.kitploit.com/production/public/readmes/56348/e0fe4ac39189ed9b3c4741ab5c8fb3276484a482dcb476b11e14381700647afd/5f586685c93346bd1df629ea4092a5a61146d0a32c2d258dfba620b3dd984161-display-v1.webp)

- El resto del mapa de ATT&CK, la kill-chain correlacionada, la cobertura de detección junto al desglose del socket de Docker, y la tabla de IOC:
![dashboard-kill-chain-2](https://assets.kitploit.com/production/public/readmes/56348/f4479575da20da3a4028a0abaac1c3b565c5b034582b157730599a15601e195f/8b18bbbdd05d8955c38f457d71029f3b2be53b409959a7560c0f8f08f038cbaf-display-v1.webp)


## 7. Mapeo de ATT&CK

| Táctica              | Técnica                                                   | Evidencia                                                                                               |
| -------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Acceso Inicial       | T1190 - Exploit Public-Facing Application                 | Peticiones de control/plant/execute (§5.1); disparo de firma ET de Suricata, §5.4                       |
| Ejecución            | T1059.004 - Command and Scripting Interpreter: Unix Shell | Tarea `Commands` de Kestra, árbol de procesos del host (`07-kestra-process-tree.png`); regla de Falco, §6.1 Detección 02 |
| Comando y Control    | T1095 - Non-Application Layer Protocol                    | Reverse shell TCP cruda vía `/dev/tcp/` - sin uso de framing C2 de capa de aplicación                   |
| Descubrimiento       | T1613 - Container and Resource Discovery                  | Enumeración de imágenes Docker a través del socket (`10-docker-images-enum.png`)                        |
| Escalada de Privilegios | T1610 - Deploy Container                               | Creación/inicio de contenedor hermano vía la API de Docker (`11`–`15`); registros EXECVE de auditd, §6.1 Detección 03 |
| Escalada de Privilegios | T1611 - Escape to Host                                 | Confirmación de root en el host, coincidencia de hostname/kernel (`16`, `17`)                           |
| Persistencia         | T1098.004 - Account Manipulation: SSH Authorized Keys     | Implante de clave en `/root/.ssh/authorized_keys` (`23`)                                                |
| Movimiento Lateral   | T1021.004 - Remote Services: SSH                          | Inicio de sesión root exitoso basado en clave (`24`); journald, §6.1 Detección 04                       |
| Persistencia         | T1053.003 - Scheduled Task/Job: Cron                      | Baliza de cron, confirmada disparándose según lo programado (`25`); §6.1 Detección 05                   |

## 8. Remediación y Endurecimiento

**Corrección principal.** Actualizar a Kestra 1.0.45 (línea 1.0.x) o 1.3.21+ (línea 1.3.x). Esto por sí solo cierra el bypass de autenticación - la Etapa 1 de este ejercicio - y es
la única corrección que no requiere controles compensatorios adicionales una vez aplicada. Ver [GHSA-2q47-568g-9h4f](https://github.com/kestra-io/kestra/security/advisories/GHSA-2q47-568g-9h4f).

**Si el parcheo inmediato no es posible**, controles compensatorios, en orden de impacto:

1. **Aplicación en el proxy inverso** - dado que el filtro vulnerable solo falla con el sufijo de ruta crudo, un proxy inverso delante de Kestra (Caddy, en este laboratorio) puede aplicar de forma independiente la autenticación en cualquier ruta que coincida con `/api/v1/*/(flows|executions)/.*` sin importar en qué termine, cerrando el bypass en una capa que el bug de la aplicación no puede alcanzar.
   
2. **Restringir el montaje del socket de Docker** - esto cierra las Etapas 2–3 por completo, independientemente del parche de Kestra. No montes con bind `/var/run/docker.sock` dentro del contenedor de Kestra. Si el ejecutor de tareas `Docker` es genuinamente necesario, usa un proxy de socket con alcance limitado (p. ej. `docker-socket-proxy`) que permita en lista blanca llamadas específicas a la API en lugar de otorgar acceso completo al daemon - el acceso completo al socket equivale a root en el host, como se demostró en la §5.2.
   
3. **Endurecimiento de SSH** - el primer mecanismo de la cadena de persistencia dependía de que root fuera alcanzable vía SSH basado en clave. `PermitRootLogin no` (o requerir un bastión/MFA para root) habría bloqueado esa ruta de persistencia específica independientemente del RCE inicial - vale la pena hacerlo con independencia de este CVE.
   
4. **Cobertura de detección provisional** - las búsquedas de correlación de Splunk y la regla personalizada de Falco, todas desplegadas y verificadas durante este ejercicio, proporcionan la cobertura provisional para las etapas de esta cadena específica mientras se programa el parcheo.

**Higiene post-incidente**, si este patrón se encuentra ya explotado: trátalo como un compromiso total del host, no solo de la aplicación - rota cada credencial y secreto a los que la instancia de Kestra tenía acceso (entradas del almacén KV, credenciales de conexión para sistemas posteriores), no solo el propio acceso de Kestra.

**Estado en el mundo real.** `CVE-2026-49869`, el aviso gemelo para este mismo bug, está listado en el catálogo KEV de CISA y vinculado a campañas observadas de criptominería y robo de credenciales en la nube. `CVE-2026-53576` (este informe) no tiene su propia entrada en KEV, pero es la misma vulnerabilidad. Las herramientas de gestión de vulnerabilidades que rastrean solo uno de los dos números CVE pueden subreportar la exposición.


## 9. Referencias

- Aviso de Seguridad de Kestra - [GHSA-2q47-568g-9h4f](https://github.com/kestra-io/kestra/security/advisories/GHSA-2q47-568g-9h4f) (CVE-2026-53576, fuente principal de este informe)
- Aviso gemelo - [GHSA-5vc5-wxxq-3fjx](https://github.com/kestra-io/kestra/security/advisories/GHSA-5vc5-wxxq-3fjx) (CVE-2026-49869, bug idéntico, listado en KEV de CISA)
- CVE.org - [CVE-2026-53576](https://www.cve.org/CVERecord?id=CVE-2026-53576), [CVE-2026-49869](https://www.cve.org/CVERecord?id=CVE-2026-49869)
- Catálogo de Vulnerabilidades Explotadas Conocidas de CISA - https://www.cisa.gov/known-exploited-vulnerabilities-catalog (entrada de CVE-2026-49869, añadida el 2026-09-02)
- Versiones corregidas, ambas confirmadas como existentes y etiquetadas - [v1.3.21](https://github.com/kestra-io/kestra/releases/tag/v1.3.21) (2026-06-02, el changelog referencia explícitamente "potential authentication bypass in the authentication filter"), [v1.0.45](https://github.com/kestra-io/kestra/releases/tag/v1.0.45) (2026-06-03)
- Técnica de escalada del socket de Docker (§5.2) - [HackTricks: Docker Breakout / Privilege Escalation](https://hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/index.html), [Trail of Bits: Understanding Docker Container Escapes](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/), [MindPatch: Docker Escape](https://www.mindpatch.net/posts/docker-escape/)
- Regla de Sigma (§6.2) - la regla pública que usé en lugar de escribir la mía propia: [SigmaHQ "Suspicious Reverse Shell Command Line"](https://github.com/SigmaHQ/sigma/blob/master/rules/linux/builtin/lnx_shell_susp_rev_shells.yml) (id `738d9bcf-6999-4fdb-b4ac-3033037db8ab`, Florian Roth / Nextron Systems), usada bajo la [Detection Rule License 1.1](https://github.com/SigmaHQ/sigma/blob/master/LICENSE.Detection.Rules.md)
- Regla de Falco (§6.3) - la brecha del socket de Docker es una solicitud abierta upstream ([falcosecurity/falco #2940](https://github.com/falcosecurity/falco/issues/2940)); la regla personalizada sigue el patrón de [los ejemplos de Docker + Falco de Sysdig](https://www.sysdig.com/blog/docker-falco-security)
Descargar herramienta
2026-09-22 a 09-24
Esta reproducción en laboratorio, construcción de detección y validación entre capas