
Riproduzione end-to-end e rilevamento cross-layer di CVE-2026-53576, la RCE non autenticata in Kestra — spinta oltre il PoC di base per mostrare come una comune misconfigurazione del socket Docker trasformi il root del container in una compromissione completa dell'host.
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 |
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.
In secondo luogo, il router di Kestra continua a instradare quei percorsi simili ai loro gestori reali e sensibili. `/api/v1/main/flows/configs` raggiunge il gestore di creazione dei flow. `/api/v1/main/executions/configs/configs` raggiunge il gestore delle esecuzioni. Il filtro li lascia passare entrambi come pubblici, e il router li esegue comunque. Assegna a un flow il namespace e l'ID `configs`, e un endpoint che esegue codice ora termina con `/configs`, ereditando così il lasciapassare del percorso pubblico.
La coppia di richieste catturata lo mostra chiaramente. `GET /api/v1/main/flows/search` senza credenziali restituisce `401`. `POST /api/v1/main/flows/configs` con lo stesso header di autenticazione vuoto restituisce `200` e memorizza il flow (vedi §5.1).
## 5. Simulazione dell'attacco
> Ogni passaggio seguente è catturato con il proprio screenshot. Tutto viene eseguito all'interno del mio homelab isolato contro un'istanza Kestra self-hosted dietro il reverse proxy.
### 5.1 Fase 1 - bypass dell'autenticazione -> root all'interno del container Kestra
**Controllo :** `GET /api/v1/main/flows/search` senza credenziali → `401 Unauthorized`.
Conferma che l'autenticazione è applicata su una route normale.

_____
**Impianto :** Invio di `POST /api/v1/main/flows/configs` senza header di autenticazione. Il body è un flow YAML il cui `namespace` e `flow id` sono entrambi `configs`, contenente un task Commands che utilizza il Process task runner. Il server restituisce `200 OK` e memorizza il flow. Il suffisso `/configs` su una route altrimenti protetta è ciò che attiva il bypass **(vedi Sezione 4).**

**Ascolta e Attendi** : Avvio di un semplice listener usando nc a scopo di test, così intercettiamo la reverse shell.

**Trigger / Esecuzione** `POST /api/v1/main/executions/configs/configs`, senza header di autenticazione → `200 OK`, nuova esecuzione creata.

**BaaaaM :** Abbiamo ottenuto la shell, ma ricorda - siamo "isolati", `root` **MA** all'interno del container Docker di Kestra, quindi "non dovremmo" essere in grado di evadere da qui. "**beh, questo è quello che pensavo**"

Il comando del task viene eseguito come figlio diretto del processo JVM di Kestra, confermato tramite l'albero dei processi lato host, e si completa con successo secondo il log di esecuzione di Kestra stesso.
**Dashboard dei Log di Kestra**

**Albero dei Processi di Kestra**

**Risultato:** esecuzione di codice in remoto non autenticata come root, all'interno del container Kestra. Questa è la prova completa e autosufficiente di **CVE-2026-53576**.
### 5.2 Fase 2 - escalation tramite socket Docker esposto (specifico dell'homelab, non parte della CVE stessa)
Dalla shell della Fase 1, è stato trovato `/var/run/docker.sock` montato nel container - un pattern Docker-outside-of-Docker (DooD), comune quando è configurato il task runner `Docker` di Kestra stesso, poiché necessita di un daemon con cui comunicare.
Raggiungere quel socket è equivalente a **root** sull'host: l'API Docker consente a un client di configurare bind mount arbitrari dell'host e namespace PID/network dell'host per i container che genera, e il daemon dietro il socket è già in esecuzione come root sull'host.
Questo non è un exploit del kernel o di evasione dal container - è l'API Docker che fa ciò per cui è progettata, raggiunta da un punto da cui non sarebbe dovuta essere raggiungibile.
Usando il socket, ho creato un container sibling con il filesystem dell'host montato e i namespace PID e network dell'host, poi l'ho avviato.
**Nota:** durante i test è emersa anche una seconda variante più silenziosa, anche se non l'ho catturata separatamente con uno screenshot. Invece di creare sempre un nuovo container sibling, lo stesso accesso al socket consente di eseguire `POST /containers/{id}/exec` contro un container già in esecuzione, quindi non c'è alcun evento di creazione del container. Su questo host Docker ho sia Kestra che Portainer, e potrei usare l'uno o l'altro per la stessa evasione. Questo è rilevante per il rilevamento: qualsiasi regola focalizzata sulla creazione di un nuovo container privilegiato manca questa variante.
Conferma di essere root e di trovare il socket lì, non vincolato da alcuna restrizione:

Verifica che il daemon Docker sia effettivamente raggiungibile attraverso il socket:

Elenco delle immagini già presenti localmente, così non devo scaricare nulla:

Primo tentativo: un container privilegiato con il filesystem dell'host montato:

Secondo tentativo, questa volta aggiungendo i namespace PID e network dell'host:

Terzo tentativo, eseguendo il chroot direttamente nel filesystem dell'host montato:

Listener attivo e in attesa sulla porta verso cui la shell di evasione effettuerà la callback:

Avvio del container:

**Root, ma questa volta è l'host, non il container:**

Versione del kernel corrispondente all'host reale, non alla vista isolata di un container:

Aggiornamento a una shell interattiva adeguata per il resto della sessione:

### 5.3 Fase 3 - persistenza, confermata in esecuzione
Dalla shell con root sull'host ho configurato due meccanismi di persistenza indipendenti,
**Primo**, una chiave SSH. Ho verificato chi aveva già accesso :

Poi ho controllato la configurazione di sshd stesso per qualsiasi cosa che avrebbe bloccato una nuova chiave:

Ho generato una coppia di chiavi sulla macchina dell'attaccante:

Ho confermato che sshd fosse effettivamente in ascolto:

Ho inserito la chiave pubblica in `authorized_keys` di root:

E ho effettuato il login con la chiave privata corrispondente:

**PS:** Questo è un accesso root indipendente dalla catena RCE originale. Anche se Kestra viene corretto, questa chiave funziona ancora.
**Secondo**, un beacon cron. Ho inserito una callback a livello root impostata per l'esecuzione a intervalli, poi ho testato con un nuovo listener per vedere se effettivamente scattava secondo la pianificazione:

**È scattato. Un secondo punto d'appoggio sull'host, indipendente sia dalla RCE che dalla chiave SSH.**
### 5.4 Timeline della kill-chain verificata.
La timeline seguente è diversa: è interamente ricostruita da telemetria indipendente lato difensore (IDS di rete + sicurezza runtime dell'host), estratta e validata in tempo reale su dati Splunk reali.
**RCE primaria - la rete rileva la consegna, l'host conferma l'esecuzione, a 103 secondi di distanza:**
| Ora (EDT) | Livello | Evento |
| ------------ | ------------------ | -------------------------------------------------------------------------------------------- |
| 02:46:09.778 | Rete (Suricata) | Scatta la firma ET pubblica per questa esatta CVE |
| 02:47:52.277 | Host (Falco) | Reverse shell confermata all'interno del container Kestra, comando esatto e container ID catturati |
**Escalation - rete e host corroborano ciascuno indipendentemente una parte diversa dello stesso evento:**
| Ora (EDT) | Livello | Evento |
| ------------ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| 03:48:55.503 | Host (Falco) | Reverse shell dal container di escalation |
| 03:51:57.360 | Rete (Suricata) | Flusso TCP **e** un alert basato sul contenuto - la stringa letterale `uid=0(root)` è stata vista uscire dall'host in chiaro quando è stato eseguito `id` |
## 6. Detection Engineering
Ho costruito i rilevamenti contro telemetria reale catturata, poi ho testato ciascuno contro un replay. La matrice mostra dove la copertura esisteva prima che iniziassi e dove non esisteva.
### 6.0 Matrice di copertura dei rilevamenti
| Fase | Rete (Suricata) | Host (Falco) | Host (auditd/journald) | Stato |
| --- | --- | --- | --- | --- |
| Richiesta di exploit iniziale | Scatta la firma ET pubblica | Nessuna visibilità a livello applicativo | - | Coperto (preesistente) |
| Esecuzione RCE | - | Regola nativa, con tag T1059 | - | Coperto (preesistente) |
| Escalation tramite socket Docker (la tecnica) | - | Gap: intercetta solo la shell risultante, non le chiamate API di abuso del socket | I record EXECVE catturano le esatte chiamate `curl --unix-socket` | Gap trovato, colmato con auditd + una regola Falco personalizzata |
| Conferma dell'impatto dell'escalation | Alert sul contenuto dell'output `id` trapelato | Stessa regola generica sulla shell | - | Coperto (preesistente, cross-layer) |
| Persistenza SSH | - | - | journald: ciclo di vita PAM completo più fingerprint della chiave | Coperto (solo host) |
| Persistenza Cron | - | - | journald e linux_audit, due fonti, cadenza esatta di 5 minuti | Coperto (solo host) |
Il gap è l'escalation tramite socket Docker. Le regole predefinite di Falco intercettano la shell generata da un container compromesso, ma nulla nel set predefinito stabile segnala un processo che raggiunge `/var/run/docker.sock` per pilotare direttamente l'API Docker. Le regole che riguarderebbero l'avvio di container privilegiati, `Launch Privileged Container` e `Launch Sensitive Mount Container`, sono distribuite con maturità `incubating` e `sandbox`, quindi nemmeno il ruleset predefinito le carica. Ho colmato il gap con una ricerca di correlazione auditd (Rilevamento 03) e una regola Falco personalizzata (§6.3).
### 6.1 Splunk - cinque ricerche di correlazione, distribuite e pianificate
Tutte e cinque vengono eseguite in tempo reale in Splunk (`*/5 * * * *`, alert tracking abilitato, throttling per campo), non solo scritte e lasciate come testo. L'SPL completo, le note esatte sui FP, la severità, i tag MITRE e i runbook di risposta per ciascuna sono in `detections/splunk/*.spl`. La tabella di stato seguente è il risultato testato in tempo reale per ciascuna, incluso un vero bug che ho trovato e corretto.
| # | Rilevamento | MITRE | Stato |
| --- | ---------------------------------------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| 01 | Firma di exploit di rete (consuma l'alert Suricata ET) | T1190 | **Scattato** - replay storico confermato, nessun nuovo evento da allora (fuori dal lookback attuale) |
| 02 | Esecuzione RCE sull'host (regola Falco redirect-to-network) | T1059 | **Scattato** - replay storico confermato |
| 03 | Abuso del socket Docker (auditd, il gap-closer) | T1610, T1611 | **Scattato sullo stesso scheduler in tempo reale** - `triggered_alert_count: 1` confermato sull'esecuzione reale `*/5 * * * *`, non solo su un test manuale |
| 04 | Persistenza del login root via SSH | T1098.004, T1021.004 | **Scattato** - replay storico confermato |
| 05 | Persistenza del beacon Cron | T1053.003 | **Distribuito con un bug che ho trovato e corretto in tempo reale.** La finestra di dispatch `-10m` conteneva solo due dei tre bucket da 5 minuti richiesti dalla soglia `distinct_intervals >= 3`, quindi non poteva mai scattare nonostante il beacon fosse ancora in esecuzione nei dati reali. L'ho ampliata a `-30m` e ridistribuita - e da allora lo scheduler l'ha fatta scattare 53 volte, quindi la correzione tiene. |
La divisione del lavoro del Rilevamento 03 è deliberata: invece di reimplementare in SPL la logica della firma di Suricata stessa, o di cercare di far intercettare a Falco una tecnica a livello di socket per cui non è stato costruito, il livello SIEM qui consuma il record EXECVE di auditd delle esatte chiamate `curl --unix-socket` - la fonte di telemetria dimostratasi più affidabile per questa specifica tecnica.
1. **Rilevamento 01** - Scatto della firma ET (alert `suricata:eve`):```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")

Detection 02 - la regola redirect-to-network di Falco, suddivisa per container. L'IP di origine si sposta dall'indirizzo bridge del container Kestra (172.17.0.3, RCE primario sulla porta 4489) all'host stesso (172.66.66.67, escalation sulla porta 4491) - l'escalation da container a host resa visibile - mentre la destinazione rimane costante: il listener dell'attaccante su 172.66.66.125:

Detection 03 - record EXECVE di auditd di curl --unix-socket docker.sock:

Detection 04 - login SSH root su journald, fingerprint della chiave catturato:

Detection 05 - il beacon cron con dotfile nascosto (/usr/local/bin/.sysmon) in esecuzione come root con cadenza esatta di 5 minuti: 79 intervalli distinti in ~6,5 ore (04:30-11:00 EDT). La soglia distinct_intervals >= 3 è ciò che distingue un beacon periodico da un cron job occasionale:

Tutte e cinque distribuite come saved search pianificate (*/5 * * * *):

Prova che lo scheduler cron le esegue effettivamente, non solo che esistono: tutte e cinque eseguite 54 volte. La Detection 03 è scattata una volta (l'abuso del docker-socket, 06:35 EDT) e la Detection 05 è scattata 53 volte (il beacon cron ancora attivo). Le Detection 01/02/04 mostrano 0 attivazioni poiché si tratta di eventi storici una tantum (richiesta di exploit, RCE, login SSH) che sono usciti dalla finestra di lookback -10m, mentre un'istanza attiva o ricorrente genererebbe ancora un alert:

Il pattern reverse-shell /dev/tcp/ - usato sia nell'RCE primario che nella callback di escalation. SigmaHQ fornisce una regola per questo: "Suspicious Reverse Shell Command Line" (id 738d9bcf-6999-4fdb-b4ac-3033037db8ab, di Florian Roth presso Nextron Systems), e una delle sue keyword è bash -i >& /dev/tcp/ - esattamente ciò che è comparso nella nostra cattura.
Quindi ho preso quella regola senza modifiche (detections/sigma/lnx_shell_susp_rev_shells.yml) e ho verificato la sua keyword contro lo stesso evento Falco già catturato dalla Detection 02. Sigma non "scatta" da solo - è una firma portabile, non un motore in esecuzione - ma posso mostrare la sua keyword che colpisce telemetria reale di questa esecuzione invece di un esempio da manuale.
Regola pubblica SigmaHQ "Suspicious Reverse Shell Command Line" - la sua keyword bash -i >& /dev/tcp/ contro lo stesso evento reale della Detection 02:

detections/falco/docker_socket_abuse.yaml - distribuita sull'istanza Falco live e confermata in attivazione su un replay reale, 2026-09-24T10:27:29Z.
Il ruleset predefinito di Falco non copre questo caso. Rilevare un processo che raggiunge /var/run/docker.sock non è un'idea nuova - gli stessi esempi Falco di Sysdig lo fanno monitorando open_write sul percorso del socket - ma non esiste una regola del genere nel set fornito/predefinito (il progetto ha una richiesta aperta per una, falcosecurity/falco #2940), e l'unica regola predefinita adiacente intercetta solo le CLI docker/kubectl, non un curl --unix-socket grezzo.
Il problema: quell'approccio standard open_write-sul-socket non è scattato in questa configurazione - con modern_bpf e uno specchio passivo, il socket viene raggiunto tramite connect(), non open(). Quindi faccio il match sulla command line del processo allo spawn (spawned_process + proc.cmdline contains "docker.sock"), la stessa classe di eventi che Falco già gestisce in modo affidabile qui. Scatta due volte per chiamata - il wrapper shell e la foglia curl - con il contesto completo:```
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]
Regola Falco personalizzata attivata - "Unexpected Process Accessing Docker Socket" (T1610/T1611):

Regole Falco predefinite che si sono attivate - il set predefinito non ha una regola per il docker-socket, ed è proprio questa la lacuna:

### 6.4 Suricata - copertura pubblica esistente, regola personalizzata rinviata
Il livello di rete per l'exploit principale è già coperto da una firma pubblica di Emerging Threats, `ET WEB_SPECIFIC_APPS Kestra Unauthenticated Remote Code Execution (CVE-2026-53576)`, che si è attivata su traffico reale durante la Fase 2.
Di seguito lo stesso bypass osservato a livello di rete, e ho costruito la query a partire dal pattern della vulnerabilità. Ogni richiesta il cui path termina in `/configs` su un endpoint `flows` o `executions` è tornata `200`, mentre una route normale (`/flows/search`) ha restituito il `401` atteso.
La colonna `Attacker IP (XFF)` è l'origine HTTP reale, letta dall'header `X-Forwarded-For`: `10.10.10.106`, il mio Mac che esegue Burp. Il `src_ip` di Suricata vede solo l'hop del reverse-proxy (`172.66.66.1`). Si tratta di una macchina diversa dalla box Kali `172.66.66.125` che in seguito ha ricevuto le reverse shell e ha effettuato il login SSH, quindi l'exploit HTTP e i callback sono arrivati da host separati.

### 6.5 Dashboard
`cve_2026_53576_kill_chain` è distribuita su Splunk e contiene: KPI principali (livelli di rilevamento, tecniche ATT&CK, rilevamenti distribuiti, meccanismi di persistenza), un grafico a colonne della timeline dell'attacco colorato per livello di telemetria, una mappa della kill-chain MITRE ATT&CK con un conteggio delle evidenze in tempo reale per ogni fase, la timeline correlata rete-e-host del §5.4, la copertura dei rilevamenti per saved search pianificata, la ripartizione della tecnica del docker-socket e una tabella degli indicatori di compromissione estratta in tempo reale dai log.
- KPI, il grafico della timeline dell'attacco e l'inizio della mappa ATT&CK:

- Il resto della mappa ATT&CK, la kill-chain correlata, la copertura dei rilevamenti accanto alla ripartizione del docker-socket e la tabella degli IOC:

## 7. Mappatura ATT&CK
| Tattica | Tecnica | Evidenza |
| -------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| Initial Access | T1190 - Exploit Public-Facing Application | Richieste control/plant/execute (§5.1); attivazione della firma ET di Suricata, §5.4 |
| Execution | T1059.004 - Command and Scripting Interpreter: Unix Shell | Task `Commands` di Kestra, albero dei processi dell'host (`07-kestra-process-tree.png`); regola Falco, §6.1 Rilevamento 02 |
| Command and Control | T1095 - Non-Application Layer Protocol | Reverse shell TCP grezza su `/dev/tcp/` - nessun framing C2 a livello applicativo utilizzato |
| Discovery | T1613 - Container and Resource Discovery | Enumerazione delle immagini Docker tramite il socket (`10-docker-images-enum.png`) |
| Privilege Escalation | T1610 - Deploy Container | Creazione/avvio di container sibling tramite l'API Docker (`11`–`15`); record EXECVE di auditd, §6.1 Rilevamento 03 |
| Privilege Escalation | T1611 - Escape to Host | Conferma di root sull'host, corrispondenza hostname/kernel (`16`, `17`) |
| Persistence | T1098.004 - Account Manipulation: SSH Authorized Keys | Impianto della chiave in `/root/.ssh/authorized_keys` (`23`) |
| Lateral Movement | T1021.004 - Remote Services: SSH | Login root basato su chiave riuscito (`24`); journald, §6.1 Rilevamento 04 |
| Persistence | T1053.003 - Scheduled Task/Job: Cron | Beacon cron, attivazione confermata secondo pianificazione (`25`); §6.1 Rilevamento 05 |
## 8. Remediation & Hardening
**Fix primario.** Aggiornare a Kestra 1.0.45 (linea 1.0.x) o 1.3.21+ (linea 1.3.x). Questo da solo chiude l'auth-bypass - la Fase 1 di questo esercizio - ed è
l'unico fix che non richiede ulteriori controlli compensativi una volta applicato. Vedi [GHSA-2q47-568g-9h4f](https://github.com/kestra-io/kestra/security/advisories/GHSA-2q47-568g-9h4f).
**Se la patch immediata non è possibile**, controlli compensativi, in ordine di impatto:
1. **Applicazione tramite reverse-proxy** - poiché il filtro vulnerabile fallisce solo sul suffisso del path grezzo, un reverse proxy davanti a Kestra (Caddy, in questo lab) può applicare in modo indipendente l'autenticazione su qualsiasi path che corrisponda a `/api/v1/*/(flows|executions)/.*` indipendentemente da come termina, chiudendo il bypass a un livello che il bug dell'applicazione non può raggiungere.
2. **Limitare il mount del socket Docker** - questo chiude interamente le Fasi 2–3, indipendentemente dalla patch di Kestra. Non eseguire il bind-mount di `/var/run/docker.sock` nel container Kestra. Se il task runner `Docker` è realmente necessario, usare un socket proxy con ambito ristretto (es. `docker-socket-proxy`) che consenta in allowlist chiamate API specifiche invece di concedere accesso completo al daemon - l'accesso completo al socket equivale a root sull'host, come dimostrato nel §5.2.
3. **Hardening SSH** - il primo meccanismo della catena di persistenza dipendeva dal fatto che root fosse raggiungibile via SSH con chiave. `PermitRootLogin no` (o richiedere un bastion/MFA per root) avrebbe bloccato quel percorso di persistenza specifico indipendentemente dall'RCE iniziale - vale la pena farlo a prescindere da questa CVE.
4. **Copertura di rilevamento interinale** - le ricerche di correlazione Splunk e la regola Falco personalizzata, tutte distribuite e verificate durante questo esercizio, forniscono la copertura interinale per le fasi di questa catena specifica mentre la patch è pianificata.
**Igiene post-incidente**, se questo pattern viene trovato già sfruttato: trattare come compromissione completa dell'host, non solo dell'applicazione - ruotare ogni credenziale e segreto a cui l'istanza Kestra aveva accesso (voci del KV store, credenziali di connessione per i sistemi a valle), non solo l'accesso di Kestra stesso.
**Stato in-the-wild.** `CVE-2026-49869`, l'avviso gemello per questo stesso bug, è elencato nel catalogo KEV di CISA e legato a campagne osservate di crypto-mining e furto di credenziali cloud. `CVE-2026-53576` (questo report) non ha un'iscrizione KEV propria, ma è la stessa vulnerabilità. Gli strumenti di vulnerability management che tracciano solo uno dei due numeri CVE potrebbero sottostimare l'esposizione.
## 9. Riferimenti
- Kestra Security Advisory - [GHSA-2q47-568g-9h4f](https://github.com/kestra-io/kestra/security/advisories/GHSA-2q47-568g-9h4f) (CVE-2026-53576, fonte primaria di questo report)
- Avviso gemello - [GHSA-5vc5-wxxq-3fjx](https://github.com/kestra-io/kestra/security/advisories/GHSA-5vc5-wxxq-3fjx) (CVE-2026-49869, bug identico, elencato in CISA KEV)
- 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 (voce CVE-2026-49869, aggiunta il 2026-09-02)
- Release corrette, entrambe confermate esistenti e taggate - [v1.3.21](https://github.com/kestra-io/kestra/releases/tag/v1.3.21) (2026-06-02, il changelog fa esplicitamente riferimento a "potential authentication bypass in the authentication filter"), [v1.0.45](https://github.com/kestra-io/kestra/releases/tag/v1.0.45) (2026-06-03)
- Tecnica di escalation tramite socket Docker (§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/)
- Regola Sigma (§6.2) - la regola pubblica che ho usato invece di scriverne una mia: [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), usata sotto la [Detection Rule License 1.1](https://github.com/SigmaHQ/sigma/blob/master/LICENSE.Detection.Rules.md)
- Regola Falco (§6.3) - la lacuna del docker-socket è una richiesta aperta upstream ([falcosecurity/falco #2940](https://github.com/falcosecurity/falco/issues/2940)); la regola personalizzata segue il pattern negli [esempi Docker + Falco di Sysdig](https://www.sysdig.com/blog/docker-falco-security)
| 2026-09-22 to 09-24 | Questa riproduzione in laboratorio, costruzione delle detection e validazione cross-layer |