1 Introduction

This article shows the research, development, exploitation and responsible disclosure of a zero-day vulnerability in the CyberPanel software solution. CyberPanel is a web hosting control panel for OpenLiteSpeed and LiteSpeed Enterprise. It is alternative to cPanel or Plesk (cyberpanel.net). This vulnerability lives in version prior to 2.3.8 of CyberPanel.

2 Terminology

This chapter gives some insight into the terms used throughout this article.

Term Description
Burpsuite BurpSuite is a tool used to test and fix security problems in websites. It helps find weaknesses that hackers could exploit.
Cloud Cloud is a service that lets you store and access data or run applications over the internet instead of on your computer’s hard drive.
Opensource Open source is software with code that is made freely available for anyone to use, modify, and share.
Python Python is a popular programming language used to write software. It’s easy to learn and is used for building websites, analyzing data, automating tasks, and more.
Server A server is a powerful computer that stores data or runs services, which can be accessed by other computers over a network.
Vulnerability A vulnerability is a weakness or flaw in a system, software, or device that can be exploited by someone.

3 Obtaining the platform code

CyberPanel is an opensource software solution for managing cloud servers, which is hosted on Github. Github is a hosting service for software projects. The github link for CyberPanel is: https://github.com/usmannasir/cyberpanel. CyberPanel provides the user with an easy-to-use installer sh <(curl https://cyberpanel.net/install.sh || wget -O - https://cyberpanel.net/install.sh) which also allows to select the version to install.

CyberPanel Installer

Even when using the installer for version 2.3.9 we can choose to install another version, like the vulnerable version 2.3.7. To execute this installer root user is required to be used, thus CyberPanel also runs as the root user. The machine will restart once, when logging back into the root user the user will be greeted with the following message:

CyberPanel MoTD

I had to hide the Log in as this exposes my public IP :)

Once we now go to localhost:8090 we see the following:

CyberPanel Login page

The admin password is funky, so I change it to something that can be easily remembered using the following command adminPass Welkom01

CyberPanel Admin password

Now we can log into our CyberPanel instance using the credentials admin:Welkom01. We can check the current version that is running by selecting Version management and looking at the Current version and Build

CyberPanel Version 2.3.7

Here we can see that we’re running on version 2.3.7.

4 Identifying vulnerabilities

Since we know that the CyberPanel is written using the Python language, which can be seen from the file extensions that are used within the files. CyberPanel Python

Knowing that it is Python, I started hunting for any way that CyberPanel executes code on the underlying operating system. This is a way that Remote Code Execution can be achieved. A way to do this is to open a random file and searching for any indication of functions that can execute code:

CyberPanel Executioner

Here we can see that execPath is being parsed to the function ProcessUtilities.executioner, without making an assumption lets take a look at this executioner.

CyberPanel Executioner

The executioner function checks the current logged-in user using the getpass.getuser() function. Remember that it was required to run as root? Yeah.. spoiler alert it runs everything as root.

Since we know this we need to look at the ProcessUtilities.normalExecutioner function:

CyberPanel Normal Executioner

Funnily enough, if we were running as a different user that is not None and not root CyberPanel would still try and run it using sudo permissions! Regardless, it runs as root already :)

CyberPanel uses the following functions that can all execute code on the underlying operating system:

  • ProcessUtilities.executioner
  • ProcessUtilities.normalExecutioner
  • ProcessUtilities.sendCommand
  • ProcessUtilities.outputExecutioner
  • ProcessUtilities.customPoen
  • ProcessUtilities.BuildCommand
  • ProcessUtilities.popenExecutioner

Why would you need 7 different functions that can all execute code?? I probably missed some too!

Time to actually hunt vulnerable functions.

CyberPanel Python files

CyberPanel contains 807 Python files, ain’t no way looking through each and every one looking for a specific function.. that would take ages!

Luckily we can use grep to look quickly for us, for example with the command grep -rni "ProcessUtilities.popenExecutioner" (Normally you would go through all the functions, for this writeup the vulnerable function uses the popenExecutioner which is why I demo it here).

CyberPanel Executioner instances

After reading, theorizing and trying functions I found an interesting candidate within the websiteFunctions\website.py file. The function submitWebsiteCreation used user controlled variables that were directly parsed to the exectioner without firstly being sanitized or checked.

submitWebsiteCreation variables

The submitWebsiteCreation function uses the following user defined variables:

  • domain
  • adminEmail
  • phpSelection
  • packageName
  • websiteOwner

Now not every variable is ideal for injection, the reasoning for this are validators. Validators is the worst nightmare for a hacker as this checks if the input given by a user is actually valid.

The domain variable has a validator.

Domain validator

The adminEmail variable also has a validator.

Email validator

The phpSelection variable however does not have a validator, added bonus is that it gets parsed directly to the executor:

Non PhpSelection validator

Now we know we have a possible executor we need to actually prove that it is vulnerable.

5 Proof-of-Concept

It is possible to make a Python exploit script to test the vulnerability, however a quicker way (that also shows a lot more) is BurpSuite. BurpSuite allows us to see what is normally hidden from view, thus also improving the time required to write an exploit script.

BurpSuite Login to CyberPanel

We see a couple of interesting things, namely that the login is being made using a POST request to the /verifyLogin endpoint. It also encodes the login credentials using JSON as shown below.


   {
     "username":"admin",
     "password":"Welkom01",
     "languageSelection":"english"
   }

Furthermore CyberPanel uses a csrftoken embedded in the Cookie, aswell as a X-Csrftoken in the header. Once we forward the requests within BurpSuite we can see we’ve now obtained a sessionid which indicates that we’re authenticated with our CyberPanel instance.

CyberPanel Session

We can now move to the vulnerable page that calls our vulnerable function. This can be found under the Websites tab and Create Website

CyberPanel Create Website

Intercepting this request using BurpSuite we get to see the following:

CyberPanel Create Website Code

We know the vulnerability lies within the phpSelection variable, so lets see what happends when we send our exploit by adding '; touch /tmp/PoC; # to the end of phpSelection.

Exploit Attempt Error

We see that our exploit attempt is stopped, because it filters characters like $ & ( ) [ ] { } ; :. Lets see how the function that is responsible for this actually works. We can find this function by using grep -rni "Data supplied is not accepted":

Exploit Attempt Error

We can see that the file CyberCP\secMiddleWare.py is responsible for stopping our exploit attempt, lets see if we can bypass this filter.

Filter

The filter looks to be filtering every character that is used for Command Injection. There is one HUGE mistake tho.. and that is the assumption that only POST can be used to submit data. OPTIONS can do exactly the same.. So changing the method from POST to OPTIONS we get the following result:

Filter

When looking at /tmp/ location using ls -la we see the following:

Filter

The owner of the file is root which proves that the command is being executed as the root user. We can further prove this by issuing a whoami and id and outputting it to this file. Instead of PHP 8.0'; touch /tmp/PoC; # we use PHP 8.0'; whoami > /tmp/PoC && id >> /tmp/PoC; #

Whoami

To do the exploit, we need the csrftoken and sessionid. The csrftoken is the same as the X-Csrftoken.

Whoami

Lastly we need the headers and payload to actually exploit the vulnerability:

Whoami

The full PoC code is available on: https://github.com/ThottySploity/CVE-2024-53376

6 Mitigation

To mitigate this vulnerability, the core problem needs to be handles which is the only sanitization of POST requests. Ideally any method is sanitized.

7 Responsible Disclosure

  • 30.10.2024 - Identified vulnerability
  • 31.10.2024 - Contacted Usman Nasir, owner of CyberPanel
  • 02.11.2024 - Usman fixed the issue and published a fix
  • 03.11.2024 - Requested CVE-ID from MITRE
  • 23.11.2024 - MITRE reserved CVE-ID 2024-53376
  • 15.12.2024 - CVE-2024-53376 published to the public

8 References