Earlier this year, researchers at Immersive Labs responsibly disclosed several vulnerabilities in Centos Web Panel, which was recently rebranded as Control Web Panel (CWP).

The vulnerabilities we found allowed malicious actors to take over accounts and run commands as root on vulnerable servers. There were hundreds of thousands of them online – millions of websites could have been affected.

Fully patched and totally safe now, MITRE assigned the following CVEs for the vulnerabilities we reported:

  • CVE-2022-25046: Path traversal vulnerability leading to remote code execution (RCE)
  • CVE-2022-25047: Account hijack via the password reset token
  • CVE-2022-25048: As a standard user execute commands in the context of root

What is CWP?

CWP is a shared hosting platform built to run on CentOS servers. It’s shared hosting services mean that even a single web server running CWP can host many websites.

The server operator creates standard user accounts for each new customer – effectively giving them their own slice of the resources on the shared server.

As with most things, there are pros and cons to this sort of setup. The positive aspect is the financial benefit; monthly running costs for both the operator and the customer are low because a single server is capable of running thousands of websites.

The downsides are that if the single host goes down, so too does every website it hosts. Even more concerning however, is that if the main host gets compromised, so will every account that’s provisioned on the server.


Shodan shows there are approximately 185,000 active CWP servers on the internet. Each one likely runs between 10 and 100 websites, meaning any vulnerability on the underlying server software could impact millions of individual websites.

CWP caters to personal and small business accounts rather than large enterprises. But a wide “watering hole” attack would still have a fairly large potential threat surface.

Attackers exploiting these vulnerabilities at scale could infect millions of websites with credential harvesting malware or target payment portals to intercept or modify banking details.


At the time of writing, all the reported vulnerabilities have been patched by the team at CWP.

In its default configuration, CWP is able to automatically apply updates at regular frequencies, meaning that all CWP instances should be fully patched unless updates have been forcibly disabled.

To check your installed version, SSH onto the target server and run the following command:
cat / path to version.php

How we found them

The next few paragraphs will go into a bit more technical detail about how we found the vulnerabilities, as well as how they work.

CVE-2022-25046: Path traversal vulnerability leading to remote code execution

Back in January, Octagon published a blog post discussing a CVE that chained two old vulnerabilities together to achieve pre-authenticated RCE. When we took a closer look at the way the vulnerabilities worked, we realized they only affected an older version of the application. In fact, most of the functions mentioned no longer existed.

So we looked deeper at the mitigations on the Octagon post. We spotted that the code on the latest version had been further modified, with the addition of htmlspecialchars and strip_tags. These functions are designed to stop XSS attacks by filtering and removing HTML tags that are frequently used for them.

However, the unintended side effect of this extra security means that we now have a new (and trivial) method to bypass the directory traversal filtering.

In this function, the first check is for a string comparison that looks for .., and checks to see if the null byte trick is being used – as reported by Octagon.

From here, the function removes any whitespace from the ends, replaces any null bytes, then filters an HTML.

Then comes the issue. If you send a string like variable=../, the first check is fine as .. isn’t present. But after the final strip tags, you’re left with variable=../../.

With a way to bypass the checks, you can now perform a standard directory traversal attack.

We searched for existing functions that could be used to run OS commands, and actually found a command injection vulnerability that we chained together with the filter bypass to gain code execution.

PoC scripts can be found on the Immersive Labs GitHub.

CVE-2022-25047: Account hijack via the password reset token

When reviewing the authentication flows used by CWP, we noticed that the password reset token generation didn’t include any elements that were secret or random. In fact, every element of the password reset token could be calculated if you had the email address and username of any given user, which is just as unfortunate as it sounds.

To exploit this vulnerability, all an attacker needs to do is trigger a valid password reset for a known account and intercept the response. The server response will contain the date and time that that password reset was requested. The date returned by the server will match within a few milliseconds the date that was used to generate the reset token.

This reset token can now be used to set a new password for the account without needing access to the target’s email account.

Check out our PoC script here.

It’s worth noting that this attack won’t work for the root account, instead generating and sending a password reset email to the user account. Although, as with most password resets, it does say you can ignore this email if you didn’t initiate the reset.

CVE-2022-25048: As a standard user execute commands in the context of root

Because CWP is a shared hosting platform, there are many site administrators that are given access to manage their part of the server. They should only be able to interact with the files and configuration of their domains and not anyone else’s.

During our research, we were able to identify several instances of command injection vulnerabilities that would allow any standard user account to run commands as root and therefore gain access to the full system.

In each example the cause is the same: input data from the user is used to create a shell command that’s then executed in the context of the root account.


We reported the vulnerabilities to the CWP team as soon as we confirmed our findings were valid. The developers were quick to respond and worked with us to patch and test all the fixes that were released.

CWP has an aggressive automatic update process that includes forced expiry of instances that aren’t kept up to date. The forced expiry date for all vulnerable versions has now passed, which is why we chose to publish these details in full now, and not sooner.

CWP offered us a bounty for disclosing the vulnerabilities responsibly. Instead, we asked it to make a donation to Save the Children in support of Ukraine – and it did.