
Kestra Auth-Bypass-Schwachstellenprüfer
Scannt Kestra-Instanzen auf die endsWith("/configs")-Authentifizierungsfilter-Umgehung. In Kestras AuthenticationFilter.java wird request.getPath().endsWith("/configs") anstelle einer exakten Pfadübereinstimmung mit /api/v1/configs geprüft. Da Kestra Ressourcen über vom Aufrufer wählbare Pfadsegmente (Namespace, Flow-ID) adressiert, umgeht jeder Pfad, der auf /configs endet, die Basis-Authentifizierung und ermöglicht unauthentifizierte Flow-Erstellung und RCE. (CVSS 10.0)
Referenzen:
GET /api/v1/configs (muss 200 zurückgeben; Antworttext wird auf Kestra-Version geparst)GET /api/v1/{tenant}/flows (sollte 401/403 zurückgeben, falls Auth erzwungen wird)/configs enden; falls eine davon nicht 401/403 zurückgibt, während die Auth-Prüfung 401/403 erzwingt, ist die Instanz verwundbar--aggressive) sendet zusätzlich PUT-Anfragen, um die Schreib-Bypass-Fähigkeit zu bestätigen--rce) – vollständige Kette: Shell/Python-Flow erstellen → Ausführung anstoßen → Logs abrufen → Codeausführung bestätigen → Bereinigung--ssrf) – erstellt einen Flow mit Pebbles http(), der auf AWS-/GCP-/Azure-Cloud-Metadaten und interne Endpunkte zielt, und prüft dann Logs auf Hinweise--destructive) – sendet DELETE an Pfade für Flows, Dashboards und Logs, um eine Umgehung destruktiver Operationen zu bestätigen| Sonde | Methode | Pfad | Beschreibung |
|---|---|---|---|
| Public Configs | GET | /api/v1/configs | Lebendcheck + Versionsextraktion |
| Protected Normal | GET | /api/v1/{tenant}/flows | Auth-Erzwingungs-Baseline |
| Flows Bypass | GET | /api/v1/{tenant}/flows/{namespace}/configs | Flow-Auflistungs-Bypass |
| Executions Bypass | GET | /api/v1/{tenant}/executions/{namespace}/configs | Ausführungs-Bypass |
| KV Store Bypass | GET | /api/v1/{tenant}/namespaces/{namespace}/kv/configs | KV-Lese-Bypass |
| Dashboards Bypass | GET | /api/v1/{tenant}/dashboards/configs | Dashboard-Bypass |
| Logs Bypass | GET | /api/v1/{tenant}/logs/{namespace}/configs | Log-Zugriffs-Bypass |
| Templates Bypass | GET | /api/v1/{tenant}/templates/{namespace}/configs | Template-Lese-Bypass |
--aggressive)| Sonde | Methode | Pfad | Beschreibung |
|---|---|---|---|
| Flows PUT Bypass | PUT | gleicher Pfad wie Flows Bypass | Erstellt einen minimalen debug.Return-Flow |
| KV PUT Bypass | PUT | gleicher Pfad wie KV Bypass | Erstellt einen KV-Eintrag {"scanned": true} |
--destructive)| Sonde | Methode | Pfad | Beschreibung |
|---|---|---|---|
| Flows DELETE Bypass | DELETE | gleicher Pfad wie Flows Bypass | Löscht eine Ressource namens "configs" |
| Dashboards DELETE Bypass | DELETE | gleicher Pfad wie Dashboards Bypass | Löscht ein Dashboard namens "configs" |
| Logs DELETE Bypass | DELETE | gleicher Pfad wie Logs Bypass | Löscht Audit-Logs |
--rce)Wird nur ausgeführt, wenn Auth-Bypass bestätigt wurde. Die vollständige Kette aus dem Advisory:
| Schritt | Methode | Pfad | Beschreibung |
|---|---|---|---|
| 1. RCE-Flow erstellen | PUT | /api/v1/{tenant}/flows/{namespace}/configs | Stellt Flow mit io.kestra.plugin.scripts.shell.Commands bereit (echo <marker>, id, hostname). Fallback auf io.kestra.plugin.scripts.python.Script bei Fehlschlag. |
| 2. Ausführung anstoßen | POST | /api/v1/{tenant}/executions/{namespace}/configs | Startet den Flow über den Bypass-Pfad |
| 3. Logs abfragen | GET | /api/v1/{tenant}/logs/search?executionId=<id> | Fragt bis zu --poll-retries-mal (Standard 10) alle --poll-interval Sekunden (Standard 3) die Logs ab, sucht nach dem eindeutigen RCE-Marker |
| 4. Bereinigung | DELETE | gleicher Pfad wie Schritt 1 | Entfernt den bereitgestellten Flow |
--ssrf)Wird nur ausgeführt, wenn Auth-Bypass bestätigt wurde:
| Schritt | Methode | Pfad | Beschreibung |
|---|---|---|---|
| 1. SSRF-Flow erstellen | PUT | /api/v1/{tenant}/flows/{namespace}/configs | Stellt einen debug.Return-Task mit Pebble-http()-Aufrufen an AWS (169.254.169.254/latest/meta-data/ami-id), GCP (metadata.google.internal), Azure (169.254.169.254/metadata/instance) und intern (127.0.0.1:8080/api/v1/configs) bereit |
| 2. Ausführung anstoßen | POST | gleicher Pfad wie RCE Schritt 2 | Löst den Flow aus |
| 3. Logs abfragen | GET | /api/v1/{tenant}/logs/search?executionId=<id> | Prüft auf Cloud-Metadaten-Indikatoren (ami-, i-, 169.254.169.254, metadata.google.internal usw.) |
| 4. Bereinigung | DELETE | gleicher Pfad wie Schritt 1 | Entfernt den bereitgestellten Flow |
positional:
target Einzelne Ziel-URL (z. B. http://localhost:8080)
options:
-f, --file Datei mit Zielen (eines pro Zeile)
-t, --timeout Request-Timeout in Sekunden (Standard: 10)
--verify-ssl TLS-Zertifikate überprüfen
-j, --json JSON-Ausgabe auf stdout
-o, --output JSON-Bericht in Datei schreiben
--tenant Tenant-Name (Standard: "main")
--namespace Namespace für Bypass-Pfade (Standard: "tutorial")
-w, --workers Thread-Anzahl für Bulk-Scans (Standard: 10)
-a, --aggressive PUT-Anfragen senden, um Schreib-Bypass zu bestätigen
-P, --auto-ports Ports für Auto-Expand (Standard: 8080 8081 8088 8091 80 443)
advanced probes:
-r, --rce RCE-Verifikationskette aktivieren (Shell + Python-Flow,
Ausführungsauslösung, Log-Abruf, automatische Bereinigung)
-s, --ssrf SSRF-Erkennung aktivieren (Pebble http() zu Cloud-Metadaten-
Endpunkten, log-basierte Beweissammlung)
-d, --destructive DELETE-Sonden auf Flows, Dashboards und Logs aktivieren
(LÖSCHT Ressourcen auf verwundbaren Instanzen)
--poll-interval Sekunden zwischen Log-Abfragen für RCE/SSRF-Ketten (Standard: 3)
--poll-retries Maximale Log-Abfrageversuche für RCE/SSRF-Ketten (Standard: 10)
Vollständige, je Sonde aufgeschlüsselte Ausgabe mit Anreicherung (Version, RCE, SSRF, DELETE-Status) und Urteil:
====================================================================
Ziel: http://10.0.0.1:8080
Zeitstempel: 2026-06-30T12:00:00+00:00
====================================================================
Version: 1.3.20 (BETROFFEN)
RCE: BESTÄTIGT via shell
| SCAN_RCE_a1b2c3d4e5f6
| uid=0(root) gid=0(root) groups=0(root)
SSRF: ERKANNT
| Indikatoren gefunden: ami-, 169.254.169.254, 127.0.0.1:8080
DELETE-BYPASS: BESTÄTIGT (destruktive Operationen umgehen Auth)
[Flows Bypass]
URL: http://10.0.0.1:8080/api/v1/main/flows/tutorial/configs
Status: 200
Bypass: JA
[Exec Bypass]
URL: http://10.0.0.1:8080/api/v1/main/executions/tutorial/configs
Status: 404
Bypass: Nein
...