Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Einreichen
ToolsExploitsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
Kestra-cve-2026-53576 — End-to-End-Reproduktion und Cross-Layer-Erkennung von CVE-2026-53576, der unauthentifizierten RCE in Kestra — über den Basis-PoC hinausgeführt, um zu zeigen, wie eine häufige Docker-Socket-Fehlkonfiguration Container-Root in eine vollständige Host-Kompromittierung verwandelt. | Kitploit
Tools/GitHubGitHub/atlasvector/kestra-cve-2026-53576
Privilege EscalationContainer-SicherheitPersistenzmechanismenSchwachstellenanalyseExploitationPost-ExploitationPenetrationstestsPapers & ForschungRed Teaming

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
Incident Response
Labs & Praxis
GitHubatlasvector/kestra-cve-2026-53576

Kestra-cve-2026-53576

End-to-End-Reproduktion und Cross-Layer-Erkennung von CVE-2026-53576, der unauthentifizierten RCE in Kestra — über den Basis-PoC hinausgeführt, um zu zeigen, wie eine häufige Docker-Socket-Fehlkonfiguration Container-Root in eine vollständige Host-Kompromittierung verwandelt.

Repository anzeigen
vor 2 TagenNoch nicht geprüft

Unauthentifizierte RCE in Kestra über einen Trailing-Path-Auth-Bypass (CVE-2026-53576)

Inhalt

  • Zusammenfassung für Führungskräfte
  • 1. Zusammenfassung
  • 2. Betroffene / Behobene Versionen
  • 3. Testumgebung & Vorabprüfung
  • 4. Ursache
  • 5. Angriffssimulation
  • 6. Detection Engineering
  • 7. ATT&CK-Mapping
  • 8. Behebung & Härtung
  • 9. Referenzen

Zusammenfassung für Führungskräfte

Kestra, eine Open-Source-Plattform zur Workflow-Orchestrierung, lieferte einen Authentifizierungsfilter aus, der anhand der Prüfung, ob die URL mit /configs endet, entschied, ob eine Anfrage Anmeldedaten benötigte - eine Prüfung, die eigentlich nur einen harmlosen öffentlichen Endpunkt freigeben sollte.

Da die Prüfung nur das Ende der Zeichenkette betrachtete, übersprang jede Anfrage, deren URL zufällig so endete, die Authentifizierung vollständig - einschließlich Endpunkten, die beliebigen Code erstellen und ausführen. Das Ergebnis: Jeder, der eine verwundbare Kestra-Instanz über das Netzwerk erreichen kann, kann Befehle als root ohne jegliche Anmeldedaten ausführen - kein Phishing, kein Erraten von Passwörtern, kein Schritt zur Rechteausweitung erforderlich.

In dieser Übung wurde diese einzelne Lücke durchgängig gegen eine selbst gehostete Lab-Instanz geführt:

  • Unauthentifizierte Codeausführung.
  • Entdeckung eines exponierten Docker-Sockets.
  • Eskalation zu vollständigem root-Zugriff auf dem zugrunde liegenden Host.
  • Zwei unabhängige Persistenzmechanismen (ein SSH-Backdoor-Schlüssel und ein geplanter Beacon).

Jede Phase wurde gegen defensive Telemetrie erfasst (Netzwerk-IDS, Host-Runtime-Sicherheit, Linux-Audit und Systemprotokolle).

Geschäftliche Auswirkung bei Nicht-Patchen: vollständige Kompromittierung des Hosts, auf dem Kestra läuft, nicht nur der Anwendung - und damit einhergehend alles andere, was von diesem Host aus erreichbar ist.

Behebung: Upgrade auf Kestra 1.0.45 / 1.3.21 oder später (der Patch allein schließt die primäre Schwachstelle; die Eskalations- und Persistenzphasen erfordern eine separate, unabhängige Behebung - den Docker-Socket nicht in Anwendungscontainer einbinden, siehe Abschnitt 8).

1. Zusammenfassung

Dieser Bericht dokumentiert CVE-2026-53576, eine unauthentifizierte Remote-Code-Execution-Schwachstelle mit CVSS 10.0 in Kestra ≤1.3.20, verursacht durch einen Path-Suffix-Authentifizierungs-Bypass (AuthenticationFilter.java, endsWith("/configs")).

Ein Angreifer, der den Namespace und die ID eines Workflows configs nennt, kann beliebige Shell-Befehle ohne Anmeldedaten als root innerhalb des Kestra-Containers erstellen und ausführen. Behoben in 1.0.45 und 1.3.21. Derselbe Fehler wurde auch unabhängig unter CVE-2026-49869 gemeldet, der im CISA KEV aufgeführten Nummer, die mit realer Ausnutzung in freier Wildbahn verbunden ist. Beide sollten zusammen zitiert werden, da öffentliche Quellen und Scanner auf eine der beiden verweisen können.

2. Betroffene / Behobene Versionen

VerwundbarKestra ≤ 1.3.20 (und vor 1.0.45 auf der 1.0.x-Linie)
Behoben1.0.45 / 1.3.21+
CVECVE-2026-53576
ZwillingshinweisCVE-2026-49869 - derselbe Fehler, im CISA KEV aufgeführt (in freier Wildbahn)

Zeitlinie

DatumEreignis
2026-06-02Kestra 1.3.21 veröffentlicht; Changelog verweist auf einen "potenziellen Authentifizierungs-Bypass im Authentifizierungsfilter"
2026-06-03Kestra 1.0.45 auf der 1.0.x-Linie veröffentlicht
2026-09-02CVE-2026-49869 (der Zwillingshinweis) zum CISA KEV-Katalog hinzugefügt

3. Testumgebung & Vorabprüfung

Selbst gehostetes Homelab: - Debian-Host (Hostname docker, Kernel 6.12.107+deb13-amd64), - Docker Engine 29.8.1. - Kestra bereitgestellt als offizielles kestra/kestra:v1.3.20-Image, erreichbar über einen Caddy-Reverse-Proxy unter kestra.int.atlasvec.com. - Telemetrie-Stack unter Test: Falco (Runtime/eBPF, Host-Ebene), - Suricata 8.0.3 IDS (passiver SPAN-Mirror), Weiterleitung an Splunk.

Bevor ich irgendetwas anfasste, bestätigte ich, dass das Ziel tatsächlich verwundbar war und der Telemetrie-Stack aktiv war. Ich erstellte außerdem einen Snapshot des Zustands vor dem Angriff, damit ich nach Abschluss zurückrollen konnte.

Kestra mit der verwundbaren Version: 01-kestra-version-v1.3.20

Der Container selbst, aktiv und erreichbar: 06-docker-kestra-running

Falcos Units auf dem Host geladen: 02-falco-units-one-active

Falco sendet aktiv Ereignisse (moderner eBPF-Modus): 03-falco-modern-bpf-active-emitting

Suricatas Dienst aktiv: 04-suricata-systemctl-active

Und seine eve.json, die Live-Ereignisse schreibt: 05-suricata-eve-json-live

4. Ursache

Hier treffen zwei Fehler aufeinander, nicht einer.

Erstens entscheidet der Authentifizierungsfilter, ob eine Anfrage die Authentifizierung überspringen kann, indem er das Ende des Anfragepfads abgleicht:```java // AuthenticationFilter.java — the vulnerable check, confirmed against the self-hosted v1.3.20 source if (path.endsWith("/configs")) { // treated as a public, unauthenticated path }

root@kitploit:~
Diese Prüfung existiert, um einen einzigen harmlosen Endpunkt offenzulegen, die öffentliche Instanzkonfiguration. Da `endsWith` nur das Ende des Strings liest, kann es einen sicheren Pfad nicht von jedem anderen Pfad unterscheiden, der zufällig gleich endet.

Zweitens leitet Kestras Router diese ähnlich aussehenden Pfade weiterhin an ihre echten, sensiblen Handler weiter. `/api/v1/main/flows/configs` erreicht den Flow-Create-Handler. `/api/v1/main/executions/configs/configs` erreicht den Execution-Handler. Der Filter winkt beide als öffentlich durch, und der Router führt sie trotzdem aus. Benenne den Namespace und die ID eines Flows `configs`, und ein code-ausführender Endpunkt endet nun auf `/configs`, sodass er den Freifahrtschein des öffentlichen Pfads erbt.

Das aufgezeichnete Request-Paar zeigt es deutlich. `GET /api/v1/main/flows/search` ohne Credentials liefert `401`. `POST /api/v1/main/flows/configs` mit demselben leeren Auth-Header liefert `200` und speichert den Flow (siehe §5.1).

## 5. Angriffssimulation

> Jeder Schritt unten ist mit einem eigenen Screenshot festgehalten. Alles läuft in meinem eigenen isolierten Homelab gegen eine selbst gehostete Kestra-Instanz hinter dem Reverse Proxy.

### 5.1 Stage 1 - Auth-Bypass -> root im Kestra-Container

**Kontrolle :** `GET /api/v1/main/flows/search` ohne Credentials → `401 Unauthorized`. 
Bestätigt, dass die Authentifizierung auf einer normalen Route erzwungen wird.
![01-burp-control-401](https://assets.kitploit.com/production/public/readmes/56348/2a6d266e96b2b4e09bc32c0ccf3609159eaf5bacdc204989d5572211e616e6ff/8a8bab993fd7ba08656d03ad85822001996be4c391de87c535751cc9e14542a1-display-v1.webp)
_____

**Platzieren :** Senden von `POST /api/v1/main/flows/configs` ohne Auth-Header. Der Body ist ein Flow-YAML, dessen `namespace` und `flow id` beide `configs` sind und das eine Commands-Task enthält, die den Process-Task-Runner verwendet. Der Server gibt `200 OK` zurück und speichert den Flow. Das `/configs`-Suffix auf einer ansonsten geschützten Route ist das, was den Bypass auslöst **(siehe Abschnitt 4).**
![02-burp-plant-flow-200](https://assets.kitploit.com/production/public/readmes/56348/5d2a2db2d70e9d60e7136c765a7a85f4d8b684ea945da5b84e84d85a2b05a151/1ee6d8f7efd58d22ef41b536f32acbbdd417d68ac030ed28e2d06f9d6d4ccb93-display-v1.webp)
**Lauschen & Warten** : Starten eines einfachen Listeners mit nc zu Testzwecken, damit wir die Reverse Shell abfangen.

![03-kali-listener-4444](https://assets.kitploit.com/production/public/readmes/56348/88d7d3516aaeef900bbb9b372d9006323a3d7391078b693124ee24710da557ac/aa9806454d3742b7e958611a5c6ed2d3dfb3072eec3c14e4bb3f050a41220803-display-v1.webp)




**Auslösen / Ausführen** `POST /api/v1/main/executions/configs/configs`, kein Auth-Header → `200 OK`, neue Execution erstellt.
![04-burp-execute-200](https://assets.kitploit.com/production/public/readmes/56348/e70d1cd38f3825dca36c25e722bdfcf4a7614b1402fe1b6d0ccebdf992738bbe/9a394373a293d22ef55e3b6ee32eae6991feac73a5ccbc7909536bdf3435172d-display-v1.webp)

**BaaaaM :** Wir haben die Shell geknackt, aber denk daran - wir sind "isoliert", `root` **ABER** innerhalb des Kestra-Docker-Containers, also "sollten" wir von hier nicht entkommen können. "**Nun, das dachte ich zumindest**"
![05-kali-revshell-container](https://assets.kitploit.com/production/public/readmes/56348/97257430abd2415f37f12c790a738d73e12f0c2509c193b1b7d24545453a1a70/9880399e445d4b8b602c1f381bbd8523a83c8c3c097b9a919e2b1871c7f1129e-display-v1.webp)


Der Befehl der Task läuft als direktes Kind des Kestra-JVM-Prozesses, bestätigt über den hostseitigen Prozessbaum, und wird gemäß Kestras eigenem Execution-Log erfolgreich abgeschlossen.

**Kestras Logs-Dashboard**
![06-kestra-ui-pwn-log](https://assets.kitploit.com/production/public/readmes/56348/b447d0d268daa119b1d64a9d7d95a588b80a7cb228613b81a6bfd69777aea7bb/467a61936f8779b533cc83a297d651957e17f9d00241ff97cc7640df917450fe-display-v1.webp)


**Kestras Prozessbaum**
![07-kestra-process-tree](https://assets.kitploit.com/production/public/readmes/56348/a7e20df484e1c5759fca4f5e403bc280ffc45b03b47dae22804321bb8398858c/0a0e30aa6c0537adf8ddd204453c8d51e808de2d5ff764fc5ad8f551cf059665-display-v1.webp)

**Ergebnis:** nicht authentifizierte Remote-Code-Ausführung als root, innerhalb des Kestra-Containers. Dies ist der vollständige, in sich geschlossene Beweis für **CVE-2026-53576**.


### 5.2 Stage 2 - Eskalation über exponierten Docker-Socket (homelab-spezifisch, nicht Teil der CVE selbst)

Aus der Stage-1-Shell wurde festgestellt, dass `/var/run/docker.sock` in den Container gemountet war - ein Docker-outside-of-Docker-(DooD)-Muster, das häufig vorkommt, wenn Kestras eigener `Docker`-Task-Runner konfiguriert ist, da dieser einen Daemon zum Ansprechen benötigt. 

Diesen Socket überhaupt zu erreichen ist gleichbedeutend mit Host-**root**: Die Docker-API erlaubt es einem Client, beliebige Host-Bind-Mounts sowie Host-PID-/Netzwerk-Namespaces für Container zu konfigurieren, die er startet, und der Daemon hinter dem Socket läuft bereits als root auf dem Host. 

Dies ist kein Kernel- oder Container-Escape-Exploit - es ist die Docker-API, die tut, wofür sie entworfen wurde, erreicht von einem Ort, von dem aus sie nicht hätte erreichbar sein sollen.

Mithilfe des Sockets erstellte ich einen Schwester-Container mit eingebundenem Host-Dateisystem sowie Host-PID- und Netzwerk-Namespaces und startete ihn dann.

**Hinweis:** Eine zweite, leisere Variante kam während des Tests ebenfalls auf, obwohl ich sie nicht separat per Screenshot festgehalten habe. Statt immer einen neuen Schwester-Container zu erstellen, erlaubt derselbe Socket-Zugriff, `POST /containers/{id}/exec` gegen einen bereits laufenden Container auszuführen, sodass überhaupt kein Container-Create-Event entsteht. Auf diesem Docker-Host habe ich sowohl Kestra als auch Portainer, von denen ich jedes für denselben Escape verwenden könnte. Das ist wichtig für die Erkennung: Jede Regel, die auf die Erstellung eines neuen privilegierten Containers abzielt, verpasst diese Variante.

Bestätigen von root und Auffinden des Sockets, der dort ohne jegliche Einschränkung liegt:
![08-docker-socket-present](https://assets.kitploit.com/production/public/readmes/56348/d2a34fd7db05bb2966a540410dbc8e76cfec416a545786349372984902b128f9/ca3ce180476010ee482b60c42687751f27a072aa2c0b78fbb6400b8406cee5e5-display-v1.webp)

Prüfen, ob der Docker-Daemon über den Socket tatsächlich erreichbar ist:
![09-docker-api-version](https://assets.kitploit.com/production/public/readmes/56348/7ce4365a9c48db827aa3c6e53c73622bef0ee7a99f530b5e37a065601b3892b0/d6debd41ca945cd5812add55df46cc5dd2f7bbaba1c88965f438ee7d5c9a4bcc-display-v1.webp)

Auflisten, welche Images bereits lokal vorhanden sind, damit ich nichts pullen muss:
![10-docker-images-enum](https://assets.kitploit.com/production/public/readmes/56348/aa1ff3ff76e92437899afc7b603925eeb53838f99f4d8586df69f8a96ff23622/34cd26942854c4c4bf59135beb54cac278aaad304faac4a3f5b64bec9e1a84de-display-v1.webp)

Erster Versuch: ein privilegierter Container mit eingebundenem Host-Dateisystem:
![11-docker-create-privileged](https://assets.kitploit.com/production/public/readmes/56348/38f4f42a486e3f46f4d798e131b3eb3bd58a7e7507b7a9e88845ed52ee32bd29/673b8ab3de93e21c6fbe23b343c4cd7fc4ddac11554ad56c0d656e2ae46467dd-display-v1.webp)

Zweiter Versuch, diesmal mit Host-PID- und Netzwerk-Namespaces:
![12-docker-create-hostns](https://assets.kitploit.com/production/public/readmes/56348/f2a5c239adbabc9b3cef7f24d2ff60b49765bfec2ec231520d18edbcaec597cb/c387405779506f4d5e8f30715d359550b69d2c1a899525b293e8b69ce61c6e73-display-v1.webp)

Dritter Versuch, direktes chroot in das gemountete Host-Dateisystem:
![13-docker-create-chroot](https://assets.kitploit.com/production/public/readmes/56348/dc38f66a291764a224f2982d22b9ca3cb37bdb31d39c48344b8030448f452e41/23519a1a158885f8b9b5691ffab18ef6eb1b5c989af00bf7c4caf6fe58ee7176-display-v1.webp)

Listener läuft und wartet auf den Port, an den die Escape-Shell zurückrufen wird:
![14-host-listener-4491](https://assets.kitploit.com/production/public/readmes/56348/37b558192ffff02366b4d219e2393d1f9fe468e82555c90a236e2cf1bdd35aa7/116c772ff659ec661cad22e023a6179eb8ffd1ebf409624b4832a27a4e947626-display-v1.webp)

Starten des Containers:
![15-docker-container-start](https://assets.kitploit.com/production/public/readmes/56348/277f7899c2fbb23d86a1918621f5efe79c635bd84af584811e98bdf37b7ab253/3f02d6a19613662df1b32fb8fa1bdbb03043f6b232844d2de3a23f552873103e-display-v1.webp)


**Root, aber diesmal ist es der Host, nicht der Container:**
![16-host-root-id](https://assets.kitploit.com/production/public/readmes/56348/0a77d4e6c239354c2c79737c51f492005cf129af8c5a595614c1005c0a125405/02ed259073555446cd67e2ce2ab86c7408fb9c2e7864ce3daac8bc50fbd2db36-display-v1.webp)

Kernel-Version entspricht dem echten Host, nicht der isolierten Sicht eines Containers:
![17-host-root-uname](https://assets.kitploit.com/production/public/readmes/56348/9f059686a831bfb8b5196412b9fd10492e8aeeb211dcb7d45fc98b3b6c0f999c/2c2dbd97e8c41b21085d9230d3b2ffb74f76c693947d9831007cff197fe3647d-display-v1.webp)


Upgrade auf eine ordentliche interaktive Shell für den Rest der Session:
![18-host-pty-upgrade](https://assets.kitploit.com/production/public/readmes/56348/34894e77c38df22cbbd807a14fd14b8e49aadc6f894d990e4022bc5b85978b62/0f81e4ed6fa6dfef8867eed194e7e4cdf12dc025b00c5763b2884530199c15d7-display-v1.webp)

### 5.3 Stage 3 - Persistenz, bestätigt ausgelöst

Aus der Host-Root-Shell richtete ich zwei unabhängige Persistenzmechanismen ein, 

**Erstens**, einen SSH-Key. Ich prüfte, wer bereits Zugriff hatte :
![19-host-authkeys-enum](https://assets.kitploit.com/production/public/readmes/56348/553f3a2b399361ce652e836fab2525686519f44dee9d94d8b7c9d45b1b939d44/0a2c697dc0f216566dba1b4cb38f134ce23ff7b57bc40dc87032016a558e2668-display-v1.webp)

Dann prüfte ich sshds eigene Konfiguration auf alles, was einen neuen Key blockieren würde:
![20-host-sshd-config-enum](https://assets.kitploit.com/production/public/readmes/56348/a25dd7b5a8376e48cee6c75e64264fa973def1db09a9d7ea520b705e32021ef3/adbfee0a5f27442b43fa318a36ef281d5abc1d998c367f2e5978b11d8282677d-display-v1.webp)

Erzeugte ein Schlüsselpaar auf der Angreifer-Box:
![21-attacker-keygen](https://assets.kitploit.com/production/public/readmes/56348/4b560189f5ab37c619d941dfedadd77a4fa8a49420aa720eafd6fccc44f7f734/f90cf5f5b1ebb76fe1505b063ef844e17c9c7b8e9f21a2f92213eb36f9428dec-display-v1.webp)

Bestätigte, dass sshd tatsächlich lauschte:
![22-host-sshd-active](https://assets.kitploit.com/production/public/readmes/56348/bd0ee4ae0a24f08b096c16eff66fd4ff87efccd92f1c1b509078d24f65af0e0f/78518194b025287cdf07b81a3335ea8b02239fcca6cbd2f32b507e28cc908cf9-display-v1.webp)

Legte den öffentlichen Schlüssel in roots `authorized_keys` ab:
![23-host-authkeys-implant](https://assets.kitploit.com/production/public/readmes/56348/e2faba217e62433f6dcd9777fa85c8dcd24858ab1c6a2f5d1293515d744003bc/0c1ca3973a85e0ade63514eaa9ad4f3d0fd63f047dc7be19b112058f24632cfd-display-v1.webp)

Und meldete mich mit dem passenden privaten Schlüssel an:
![24-ssh-root-login-proof](https://assets.kitploit.com/production/public/readmes/56348/14b698fb9eae32aff09e6ec7d179ecf1c2ef665d7b87be8d6f9fac956e68db2b/a2ced84629d34de099a598e38f71ba54411a890eaadb50a2dc8dd8dc099a6459-display-v1.webp)

**PS:** Das ist Root-Zugriff unabhängig von der ursprünglichen RCE-Kette. Selbst wenn Kestra gepatcht wird, funktioniert dieser Schlüssel weiterhin.

**Zweitens**, ein Cron-Beacon. Ich legte einen Root-Level-Callback ab, der in einem Intervall laufen sollte, und testete dann mit einem frischen Listener, ob er tatsächlich planmäßig ausgelöst wird:
![25-host-cron-persist](https://assets.kitploit.com/production/public/readmes/56348/3dfa92072c55dd052127ef69943a6c43a855534420b286e0dbd62ce833dc441f/7a75828de1e323b44a4c792a2eed2713cf656433685deef7931026f815b2dd98-display-v1.webp)

**Er wurde ausgelöst. Ein zweiter Standfuß auf dem Host, unabhängig sowohl von der RCE als auch vom SSH-Key.**


### 5.4 Verifizierte Kill-Chain-Timeline.

Die folgende Timeline ist anders: Sie ist vollständig aus unabhängiger verteidigerseitiger Telemetrie rekonstruiert (Network IDS + Host Runtime Security), live gegen echte Splunk-Daten abgerufen und validiert.

**Primäre RCE - Netzwerk erkennt die Auslieferung, Host bestätigt die Ausführung, 103 Sekunden Abstand:**

| Zeit (EDT)   | Ebene              | Ereignis                                                                                        |
| ------------ | ------------------ | -------------------------------------------------------------------------------------------- |
| 02:46:09.778 | Netzwerk (Suricata) | Öffentliche ET-Signatur für genau diese CVE wird ausgelöst                                                 |
| 02:47:52.277 | Host (Falco)       | Reverse Shell im Kestra-Container bestätigt, exakter Befehl und Container-ID erfasst |

**Eskalation - Netzwerk und Host bestätigen jeweils unabhängig einen anderen Teil desselben Ereignisses:**

| Zeit (EDT)   | Ebene              | Ereignis                                                                                                                              |
| ------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| 03:48:55.503 | Host (Falco)       | Reverse Shell aus dem Eskalations-Container                                                                                        |
| 03:51:57.360 | Netzwerk (Suricata) | TCP-Flow **und** ein inhaltsbasierter Alert - der wörtliche String `uid=0(root)` wurde beim Verlassen des Hosts im Klartext gesehen, als `id` ausgeführt wurde |


## 6. Detection Engineering

Ich baute die Detections gegen echte erfasste Telemetrie und testete dann jede einzelne gegen ein Replay. Die Matrix zeigt, wo vor meinem Beginn Abdeckung existierte und wo nicht.

### 6.0 Detection-Coverage-Matrix

| Stage | Netzwerk (Suricata) | Host (Falco) | Host (auditd/journald) | Status |
| --- | --- | --- | --- | --- |
| Initiale Exploit-Anfrage | Öffentliche ET-Signatur wird ausgelöst | Keine App-Layer-Sichtbarkeit | - | Abgedeckt (bereits vorhanden) |
| RCE-Ausführung | - | Native Regel, T1059-getaggt | - | Abgedeckt (bereits vorhanden) |
| Docker-Socket-Eskalation (die Technik) | - | Lücke: erfasst nur die resultierende Shell, nicht die Socket-Missbrauchs-API-Aufrufe | EXECVE-Datensätze erfassen die exakten `curl --unix-socket`-Aufrufe | Lücke gefunden, geschlossen mit auditd + einer benutzerdefinierten Falco-Regel |
| Bestätigung der Eskalationsauswirkung | Content-Alert auf die geleakte `id`-Ausgabe | Dieselbe generische Shell-Regel | - | Abgedeckt (bereits vorhanden, ebenenübergreifend) |
| SSH-Persistenz | - | - | journald: vollständiger PAM-Lebenszyklus plus Key-Fingerprint | Abgedeckt (nur Host) |
| Cron-Persistenz | - | - | journald und linux_audit, zwei Quellen, exakte 5-Minuten-Kadenz | Abgedeckt (nur Host) |

Die Lücke ist die Docker-Socket-Eskalation. Falcos Standardregeln erfassen die Shell, die ein kompromittierter Container startet, aber nichts im stabilen Standard-Set markiert einen Prozess, der `/var/run/docker.sock` erreicht, um die Docker-API direkt anzusteuern. Die Regeln, die privilegierte Container-Starts betreffen würden, `Launch Privileged Container` und `Launch Sensitive Mount Container`, werden mit `incubating`- und `sandbox`-Reifegrad ausgeliefert, sodass das Standard-Regelset sie ebenfalls nicht lädt. Ich schloss die Lücke mit einer auditd-Korrelationssuche (Detection 03) und einer benutzerdefinierten Falco-Regel (§6.3).

### 6.1 Splunk - fünf Korrelationssuchen, bereitgestellt und geplant

Alle fünf laufen live in Splunk (`*/5 * * * *`, Alert-Tracking aktiviert, Throttling pro Feld), nicht nur geschrieben und als Text belassen. Vollständiges SPL, exakte FP-Hinweise, Severity, MITRE-Tags und Response-Runbooks für jede einzelne sind in `detections/splunk/*.spl`. Die Status-Tabelle unten ist das live getestete Ergebnis für jede, einschließlich eines echten Bugs, den ich gefunden und behoben habe.

| #   | Detection                                                  | MITRE                | Status                                                                                                                              |
| --- | ---------------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| 01  | Netzwerk-Exploit-Signatur (konsumiert den Suricata-ET-Alert) | T1190                | **Ausgelöst** - historisches Replay bestätigt, seitdem keine neuen Events (außerhalb des aktuellen Lookback)                                             |
| 02  | Host-RCE-Ausführung (Falco-Redirect-to-Network-Regel)        | T1059                | **Ausgelöst** - historisches Replay bestätigt                                                                                             |
| 03  | Docker-Socket-Missbrauch (auditd, der Lückenschließer)               | T1610, T1611         | **Ausgelöst auf dem Live-Scheduler selbst** - `triggered_alert_count: 1` bestätigt beim echten `*/5 * * * *`-Lauf, nicht nur bei einem manuellen Test |
| 04  | SSH-Root-Login-Persistenz                                 | T1098.004, T1021.004 | **Ausgelöst** - historisches Replay bestätigt                                                                                             |
| 05  | Cron-Beacon-Persistenz                                    | T1053.003            | **Bereitgestellt mit einem Bug, den ich gefunden und live behoben habe.** Das `-10m`-Dispatch-Fenster enthielt nur zwei der drei 5-Minuten-Buckets, die der `distinct_intervals >= 3`-Schwellenwert benötigt, sodass es niemals auslösen konnte, obwohl der Beacon in echten Daten weiterhin lief. Erweiterte es auf `-30m` und stellte es erneut bereit - und der Scheduler hat es seitdem 53 Mal ausgelöst, die Korrektur hält also. |

Die Arbeitsteilung von Detection 03 ist bewusst gewählt: Statt Suricatas eigene Signaturlogik in SPL neu zu implementieren oder zu versuchen, Falco eine Socket-Level-Technik erfassen zu lassen, für die es nicht gebaut wurde, konsumiert die SIEM-Ebene hier auditds EXECVE-Datensatz der exakten `curl --unix-socket`-Aufrufe - die Telemetriequelle, die sich für diese spezifische Technik als am zuverlässigsten erwiesen hat.

1. **Detection 01** - ET-Signatur wird ausgelöst (`suricata:eve`-Alert):```spl
index=main sourcetype=suricata:eve event_type=alert
  alert.signature="ET WEB_SPECIFIC_APPS Kestra Unauthenticated Remote Code Execution (CVE-2026-53576)"
| stats count min(_time) as first_seen max(_time) as last_seen
        values(src_ip) as source_ips
  by dest_ip dest_port
| eval first_seen=strftime(first_seen,"%Y-%m-%d %H:%M:%S")
| eval last_seen=strftime(last_seen,"%Y-%m-%d %H:%M:%S")

det01-network-et-signature

  1. Detection 02 – Falcos Redirect-to-Network-Regel, aufgeschlüsselt pro Container. Die Quell-IP verschiebt sich von der Bridge-Adresse des Kestra-Containers (172.17.0.3, primäre RCE auf Port 4489) zum Host selbst (172.66.66.67, Eskalation auf Port 4491) – die Container-zu-Host-Eskalation wird sichtbar – während das Ziel konstant bleibt: der Listener des Angreifers unter 172.66.66.125: det02-falco-redirect-revshell

  2. Detection 03 – auditd-EXECVE-Datensätze von curl --unix-socket docker.sock: det03-auditd-docker-sock

  3. Detection 04 – journald-Root-SSH-Login, Schlüsselfingerabdruck erfasst: det04-ssh-root-login

  4. Detection 05 – der Cron-Beacon als versteckte Dotfile (/usr/local/bin/.sysmon), der als root in exakt 5-Minuten-Intervallen läuft: 79 verschiedene Intervalle über ~6,5 Stunden (04:30–11:00 EDT). Die Schwelle distinct_intervals >= 3 ist es, die einen periodischen Beacon von einem einmaligen Cron-Job unterscheidet: det05-cron-beacon

Alle fünf als geplante gespeicherte Suchen (*/5 * * * *) bereitgestellt: saved-searches-scheduled

Der Beweis, dass der Cron-Scheduler diese tatsächlich ausführt und nicht nur, dass sie existieren: Alle fünf wurden 54-mal ausgeführt. Detection 03 schlug einmal an (der Docker-Socket-Missbrauch, 06:35 EDT) und Detection 05 schlug 53-mal an (der weiterhin aktive Cron-Beacon). Detections 01/02/04 zeigen 0 Treffer, da es sich um einmalige historische Ereignisse handelt (Exploit-Request, RCE, SSH-Login), die aus dem -10m-Lookback-Fenster herausgefallen sind, während eine aktive oder wiederkehrende Instanz weiterhin alarmieren würde: scheduler-triggered-alert

6.2 Sigma – portable Host-Prozess-Spawn-Regel

Das /dev/tcp/-Reverse-Shell-Muster – verwendet sowohl in der primären RCE als auch im Eskalations-Callback. SigmaHQ liefert dafür eine Regel: „Suspicious Reverse Shell Command Line" (ID 738d9bcf-6999-4fdb-b4ac-3033037db8ab, von Florian Roth bei Nextron Systems), und eines ihrer Schlüsselwörter ist bash -i >& /dev/tcp/ – genau das, was in unserer Aufzeichnung auftauchte.

Also habe ich diese Regel unverändert übernommen (detections/sigma/lnx_shell_susp_rev_shells.yml) und ihr Schlüsselwort gegen dasselbe Falco-Ereignis geprüft, das Detection 02 bereits erfasst hat. Sigma „feuert" nicht von selbst – es ist eine portable Signatur, keine laufende Engine –, aber ich kann zeigen, wie ihr Schlüsselwort auf echte Telemetrie aus diesem Lauf trifft statt auf ein Lehrbuchbeispiel.

Öffentliche SigmaHQ-Regel „Suspicious Reverse Shell Command Line" – ihr Schlüsselwort bash -i >& /dev/tcp/ gegen dasselbe reale Ereignis wie Detection 02:

sigma-devtcp-match-event

6.3 Falco – benutzerdefinierte Regel schließt die Docker-Socket-Lücke

detections/falco/docker_socket_abuse.yaml – auf der Live-Falco-Instanz bereitgestellt und mit Auslösung bei einem echten Replay bestätigt, 2026-09-24T10:27:29Z.

Das Standard-Regelset von Falco deckt dies nicht ab. Einen Prozess zu erkennen, der auf /var/run/docker.sock zugreift, ist keine neue Idee – Sysdigs eigene Falco-Beispiele tun dies, indem sie auf open_write auf dem Socket-Pfad achten –, aber es gibt keine solche Regel im mitgelieferten/Standard-Set (das Projekt hat eine offene Anfrage dafür, falcosecurity/falco #2940), und die eine angrenzende Standardregel erfasst nur die docker/kubectl-CLIs, nicht ein rohes curl --unix-socket.

Der Haken: Der standardmäßige open_write-auf-dem-Socket-Ansatz löste in diesem Setup nicht aus – mit modern_bpf und einem passiven Mirror wird der Socket über connect() erreicht, nicht über open(). Also matche ich stattdessen auf die Prozess-Kommandozeile beim Spawn (spawned_process + proc.cmdline contains "docker.sock"), dieselbe Ereignisklasse, die Falco hier bereits zuverlässig verarbeitet. Sie feuert zweimal pro Aufruf – der Shell-Wrapper und das curl-Blatt – mit vollem Kontext:``` priority=Critical, container_id=d417e027d444, image=kestra/kestra:v1.3.20, user=root, cmdline="curl -s --unix-socket /var/run/docker.sock http://localhost/version", tags=[T1610, T1611]

root@kitploit:~
Benutzerdefinierte Falco-Regel, die ausgelöst wurde – „Unexpected Process Accessing Docker Socket" (T1610/T1611):
![det17-falco-custom-docker-sock](https://assets.kitploit.com/production/public/readmes/56348/6fa1b11a7c8c6a3c8619ac95a2950cf1f326df0ef1651324aa0b4f80db389a12/8ac8f1a2c5184a84ba2af0c9c85c3112506e19c62b0734105e5b74c90e4d8078-display-v1.webp)

Standard-Falco-Regeln, die ausgelöst wurden – das Standard-Set enthält keine docker-socket-Regel, was die Lücke darstellt:
![falco-rule-inventory](https://assets.kitploit.com/production/public/readmes/56348/5da667ac881b32f6bc633e58b4d00a08ea22cf3a5000b3ae8522cb3937b051a4/3fe1201158632dc6aef5257bf3620e83e087814f3da0108f7d2ef04fd5088ec9-display-v1.webp)

### 6.4 Suricata – bestehende öffentliche Abdeckung, benutzerdefinierte Regel zurückgestellt

Die Netzwerkschicht für den primären Exploit ist bereits durch eine öffentliche Emerging-Threats-Signatur abgedeckt, `ET WEB_SPECIFIC_APPS Kestra Unauthenticated Remote Code Execution (CVE-2026-53576)`, die während Phase 2 bei echtem Datenverkehr ausgelöst wurde.

Unten ist derselbe Bypass auf der Netzwerkschicht zu sehen, und ich habe die Abfrage aus dem Schwachstellenmuster erstellt. Jede Anfrage, deren Pfad auf einem `flows`- oder `executions`-Endpunkt mit `/configs` endet, kam mit `200` zurück, während eine normale Route (`/flows/search`) die erwartete `401` zurückgab.

Die Spalte `Attacker IP (XFF)` ist der echte HTTP-Ursprung, gelesen aus dem `X-Forwarded-For`-Header: `10.10.10.106`, mein Mac, auf dem Burp läuft. Suricatas eigenes `src_ip` sieht nur den Reverse-Proxy-Hop (`172.66.66.1`). Das ist eine andere Maschine als die `172.66.66.125`-Kali-Box, die später die Reverse Shells abfing und den SSH-Login durchführte, sodass der HTTP-Exploit und die Callbacks von getrennten Hosts kamen.

![suricata-raw-post-http](https://assets.kitploit.com/production/public/readmes/56348/d713d35f0d858af8dd5d477a9929ed6d07e55bce5e9e43946dfe1fb1cca73699/975155c6fe8a39a0de715497a7e5a659b17641a7ed4ed2d7f4d7bfcd02842398-display-v1.webp)

### 6.5 Dashboard

`cve_2026_53576_kill_chain` ist in Splunk bereitgestellt und enthält: Headline-KPIs (Erkennungsschichten, ATT&CK-Techniken, bereitgestellte Erkennungen, Persistenzmechanismen), ein Säulendiagramm der Angriffs-Timeline, eingefärbt nach Telemetrieschicht, eine MITRE-ATT&CK-Kill-Chain-Karte mit einer Live-Evidenzzahl pro Phase, die netzwerk- und hostkorrelierte Timeline aus §5.4, Erkennungsabdeckung nach geplanter gespeicherter Suche, die Aufschlüsselung der docker-socket-Technik und eine Live aus den Logs gezogene Tabelle mit Kompromittierungsindikatoren.

- KPIs, das Angriffs-Timeline-Diagramm und der Beginn der ATT&CK-Karte:
![dashboard-kill-chain-1](https://assets.kitploit.com/production/public/readmes/56348/e0fe4ac39189ed9b3c4741ab5c8fb3276484a482dcb476b11e14381700647afd/5f586685c93346bd1df629ea4092a5a61146d0a32c2d258dfba620b3dd984161-display-v1.webp)

- Der Rest der ATT&CK-Karte, die korrelierte Kill-Chain, die Erkennungsabdeckung neben der docker-socket-Aufschlüsselung und die IOC-Tabelle:
![dashboard-kill-chain-2](https://assets.kitploit.com/production/public/readmes/56348/f4479575da20da3a4028a0abaac1c3b565c5b034582b157730599a15601e195f/8b18bbbdd05d8955c38f457d71029f3b2be53b409959a7560c0f8f08f038cbaf-display-v1.webp)


## 7. ATT&CK-Mapping

| Taktik               | Technik                                                 | Evidenz                                                                                                |
| -------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Initial Access       | T1190 - Exploit Public-Facing Application                 | Control/plant/execute-Anfragen (§5.1); Suricata-ET-Signatur löst aus, §5.4                                 |
| Execution            | T1059.004 - Command and Scripting Interpreter: Unix Shell | Kestra-`Commands`-Task, Host-Prozessbaum (`07-kestra-process-tree.png`); Falco-Regel, §6.1 Erkennung 02 |
| Command and Control  | T1095 - Non-Application Layer Protocol                    | Rohe `/dev/tcp/`-TCP-Reverse-Shell – keine Application-Layer-C2-Framing verwendet                                |
| Discovery            | T1613 - Container and Resource Discovery                  | Docker-Image-Enumeration über den Socket (`10-docker-images-enum.png`)                                   |
| Privilege Escalation | T1610 - Deploy Container                                  | Sibling-Container-Erstellung/-Start über die Docker-API (`11`–`15`); auditd-EXECVE-Datensätze, §6.1 Erkennung 03 |
| Privilege Escalation | T1611 - Escape to Host                                    | Host-Root-Bestätigung, Hostname/Kernel-Übereinstimmung (`16`, `17`)                                              |
| Persistence          | T1098.004 - Account Manipulation: SSH Authorized Keys     | Key-Implantat in `/root/.ssh/authorized_keys` (`23`)                                                      |
| Lateral Movement     | T1021.004 - Remote Services: SSH                          | Erfolgreicher schlüsselbasierter Root-Login (`24`); journald, §6.1 Erkennung 04                                     |
| Persistence          | T1053.003 - Scheduled Task/Job: Cron                      | Cron-Beacon, bestätigte planmäßige Auslösung (`25`); §6.1 Erkennung 05                                     |

## 8. Behebung & Härtung

**Primäre Lösung.** Upgrade auf Kestra 1.0.45 (1.0.x-Zweig) oder 1.3.21+ (1.3.x-Zweig). Allein dies schließt den Auth-Bypass – Phase 1 dieser Übung – und ist
die einzige Lösung, die nach Anwendung keine weiteren kompensierenden Kontrollen erfordert. Siehe [GHSA-2q47-568g-9h4f](https://github.com/kestra-io/kestra/security/advisories/GHSA-2q47-568g-9h4f).

**Falls ein sofortiges Patchen nicht möglich ist**, kompensierende Kontrollen, nach Wirkung geordnet:

1. **Durchsetzung am Reverse-Proxy** – da der verwundbare Filter nur beim rohen Pfad-Suffix fehlschlägt, kann ein Reverse-Proxy vor Kestra (in diesem Lab Caddy) unabhängig davon die Authentifizierung für jeden Pfad erzwingen, der auf `/api/v1/*/(flows|executions)/.*` passt, unabhängig davon, womit er endet, und schließt so den Bypass auf einer Ebene, die der Anwendungsfehler nicht erreichen kann.
   
2. **Docker-Socket-Mount einschränken** – dies schließt die Phasen 2–3 vollständig, unabhängig vom Kestra-Patch. Binden Sie `/var/run/docker.sock` nicht per Bind-Mount in den Kestra-Container ein. Wenn der `Docker`-Task-Runner wirklich erforderlich ist, verwenden Sie einen eingeschränkten Socket-Proxy (z. B. `docker-socket-proxy`), der bestimmte API-Aufrufe auf eine Allowlist setzt, anstatt vollen Daemon-Zugriff zu gewähren – voller Zugriff auf den Socket entspricht Host-Root, wie in §5.2 gezeigt.
   
3. **SSH-Härtung** – der erste Mechanismus der Persistenzkette hing überhaupt davon ab, dass Root per schlüsselbasiertem SSH erreichbar war. `PermitRootLogin no` (oder die Anforderung eines Bastion/MFA für Root) hätte diesen spezifischen Persistenzpfad unabhängig von der anfänglichen RCE blockiert – lohnenswert unabhängig von dieser CVE.
   
4. **Vorläufige Erkennungsabdeckung** – die Splunk-Korrelationssuchen und die benutzerdefinierte Falco-Regel, alle während dieser Übung bereitgestellt und verifiziert, bieten die vorläufige Abdeckung für die Phasen dieser spezifischen Kette, während das Patchen geplant wird.

**Hygiene nach dem Vorfall**, falls dieses Muster bereits ausgenutzt vorgefunden wird: Behandeln Sie es als vollständige Host-Kompromittierung, nicht nur als Anwendungskompromittierung – rotieren Sie sämtliche Anmeldedaten und Geheimnisse, auf die die Kestra-Instanz Zugriff hatte (KV-Store-Einträge, Verbindungsanmeldedaten für nachgelagerte Systeme), nicht nur Kestras eigenen Zugriff.

**Status in freier Wildbahn.** `CVE-2026-49869`, der Zwillings-Hinweis für denselben Fehler, ist in CISA's KEV-Katalog aufgeführt und mit beobachteten Krypto-Mining- und Cloud-Credential-Diebstahl-Kampagnen verbunden. `CVE-2026-53576` (dieser Bericht) hat keine eigene KEV-Auflistung, ist aber dieselbe Schwachstelle. Schwachstellenmanagement-Tools, die nur eine der beiden CVE-Nummern verfolgen, melden die Exposition möglicherweise zu niedrig.


## 9. Referenzen

- Kestra Security Advisory – [GHSA-2q47-568g-9h4f](https://github.com/kestra-io/kestra/security/advisories/GHSA-2q47-568g-9h4f) (CVE-2026-53576, primäre Quelle dieses Berichts)
- Zwillings-Hinweis – [GHSA-5vc5-wxxq-3fjx](https://github.com/kestra-io/kestra/security/advisories/GHSA-5vc5-wxxq-3fjx) (CVE-2026-49869, identischer Fehler, in CISA KEV aufgeführt)
- CVE.org – [CVE-2026-53576](https://www.cve.org/CVERecord?id=CVE-2026-53576), [CVE-2026-49869](https://www.cve.org/CVERecord?id=CVE-2026-49869)
- CISA Known Exploited Vulnerabilities Catalog – https://www.cisa.gov/known-exploited-vulnerabilities-catalog (Eintrag CVE-2026-49869, hinzugefügt am 02.09.2026)
- Behobene Releases, beide bestätigt vorhanden und getaggt – [v1.3.21](https://github.com/kestra-io/kestra/releases/tag/v1.3.21) (02.06.2026, Changelog verweist explizit auf „potential authentication bypass in the authentication filter"), [v1.0.45](https://github.com/kestra-io/kestra/releases/tag/v1.0.45) (03.06.2026)
- Docker-Socket-Eskalationstechnik (§5.2) – [HackTricks: Docker Breakout / Privilege Escalation](https://hacktricks.wiki/en/linux-hardening/privilege-escalation/docker-security/docker-breakout-privilege-escalation/index.html), [Trail of Bits: Understanding Docker Container Escapes](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/), [MindPatch: Docker Escape](https://www.mindpatch.net/posts/docker-escape/)
- Sigma-Regel (§6.2) – die öffentliche Regel, die ich verwendet habe, anstatt eine eigene zu schreiben: [SigmaHQ "Suspicious Reverse Shell Command Line"](https://github.com/SigmaHQ/sigma/blob/master/rules/linux/builtin/lnx_shell_susp_rev_shells.yml) (id `738d9bcf-6999-4fdb-b4ac-3033037db8ab`, Florian Roth / Nextron Systems), verwendet unter der [Detection Rule License 1.1](https://github.com/SigmaHQ/sigma/blob/master/LICENSE.Detection.Rules.md)
- Falco-Regel (§6.3) – die docker-socket-Lücke ist ein offener Upstream-Request ([falcosecurity/falco #2940](https://github.com/falcosecurity/falco/issues/2940)); die benutzerdefinierte Regel folgt dem Muster in [Sysdig's Docker + Falco examples](https://www.sysdig.com/blog/docker-falco-security)
Tool herunterladen
2026-09-22 bis 09-24Diese Lab-Reproduktion, der Detection-Aufbau und die schichtübergreifende Validierung