
End-to-end reproduction and cross-layer detection of CVE-2026-53576, the unauthenticated RCE in Kestra - taken past the base PoC to show how a common Docker-socket misconfiguration turns container-root into full host compromise.
Kestra, una piattaforma open-source di orchestrazione di workflow, distribuiva un filtro di autenticazione che decideva se una richiesta necessitasse di credenziali verificando se l'URL terminava con /configs - un controllo pensato per esporre un unico endpoint pubblico innocuo.
Poiché il controllo esaminava solo la coda della stringa, qualsiasi richiesta il cui URL terminasse in quel modo saltava completamente l'autenticazione, inclusi gli endpoint che creano ed eseguono codice arbitrario. Il risultato: chiunque possa raggiungere via rete un'istanza Kestra vulnerabile può eseguire comandi come root senza alcuna credenziale, senza phishing, senza indovinare password, senza alcuna fase di privilege escalation.
In questo esercizio, quella singola lacuna è stata sfruttata end-to-end contro un'istanza di laboratorio self-hosted:
Ogni fase è stata catturata contro la telemetria difensiva (IDS di rete, sicurezza runtime dell'host, audit Linux e log di sistema).
Impatto sul business se non patchato: compromissione completa dell'host che esegue Kestra, non solo dell'applicazione - e per estensione di qualsiasi altra cosa raggiungibile da quell'host.
Fix: aggiornare a Kestra 1.0.45 / 1.3.21 o successiva (la sola patch chiude la vulnerabilità primaria; le fasi di escalation e persistenza richiedono un fix separato e indipendente - non montare il socket Docker nei container applicativi, vedere la Sezione 8).
Questo report documenta CVE-2026-53576, una vulnerabilità di remote code execution non autenticata con CVSS 10.0 in Kestra ≤1.3.20, causata da un bypass dell'autenticazione tramite suffisso di percorso (AuthenticationFilter.java, endsWith("/configs")).
Un attaccante che assegna al namespace e all'ID di un workflow il nome configs può creare ed eseguire comandi shell arbitrari senza credenziali, come root, all'interno del container Kestra. Corretto in 1.0.45 e 1.3.21. Lo stesso identico bug è stato segnalato anche in modo indipendente con CVE-2026-49869, che è il numero elencato nel catalogo CISA KEV legato allo sfruttamento reale in-the-wild. Entrambi dovrebbero essere citati insieme, poiché fonti pubbliche e scanner potrebbero fare riferimento all'uno o all'altro.
| Vulnerabili | Kestra ≤ 1.3.20 (e pre-1.0.45 sulla linea 1.0.x) |
| Corrette | 1.0.45 / 1.3.21+ |
| CVE | CVE-2026-53576 |
| Advisory gemello | CVE-2026-49869 - stesso bug, elencato in CISA KEV (in-the-wild) |
| Data | Evento |
|---|---|
| 2026-06-02 | Rilasciata Kestra 1.3.21; il changelog fa riferimento a un "potenziale bypass dell'autenticazione nel filtro di autenticazione" |
| 2026-06-03 | Rilasciata Kestra 1.0.45 sulla linea 1.0.x |
| 2026-09-02 | CVE-2026-49869 (l'advisory gemello) aggiunto al catalogo CISA KEV |
| 2026-09-22 to 09-24 | Questa riproduzione in laboratorio, costruzione delle detection e validazione cross-layer |
Homelab self-hosted:
- Host Debian (hostname docker, kernel 6.12.107+deb13-amd64),
- Docker Engine 29.8.1.
- Kestra distribuito come immagine ufficiale kestra/kestra:v1.3.20, raggiungibile tramite reverse proxy Caddy su kestra.int.atlasvec.com.
- Stack di telemetria in test: Falco (runtime/eBPF, a livello host),
- Suricata 8.0.3 IDS (mirror SPAN passivo), con inoltro verso Splunk.
Prima di toccare qualsiasi cosa, ho confermato che il target fosse effettivamente vulnerabile e che lo stack di telemetria fosse attivo. Ho anche acquisito uno snapshot dello stato pre-attacco per poter ripristinare una volta terminato.
Kestra in esecuzione con la versione vulnerabile:

Il container stesso, attivo e raggiungibile:

Le unit di Falco caricate sull'host:

Falco che emette attivamente eventi (modalità eBPF moderna):

Il servizio di Suricata attivo:

E il suo eve.json che scrive eventi in tempo reale:

Qui si allineano due errori, non uno solo.
Innanzitutto, il filtro di autenticazione decide se una richiesta può saltare l'autenticazione confrontando la fine del percorso della richiesta:```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 }
Quel controllo esiste per esporre un singolo endpoint innocuo, la configurazione dell'istanza pubblica. Poiché `endsWith` legge solo la coda della stringa, non riesce a distinguere quel percorso sicuro da qualsiasi altro percorso che termini allo stesso modo.