Finding XSS in a million websites (cPanel CVE-2023-29489)
cPanel is a web hosting control panel software that is deployed widely across the internet. To be exact, there are about ~1.4 million installations of cPanel exposed on the external internet at the time of writing this blog post.
We discovered a reflected cross-site scripting vulnerability that could be exploited without any authentication. In addition to this, the XSS vulnerability was exploitable regardless of whether or not the cPanel management ports (2080, 2082, 2083, 2086) were exposed externally. This means that your website on port 80 and 443 was also vulnerable to the cross-site scripting vulnerability if it is being managed by cPanel.
For those that are worried that their website is affected by this vulnerability, please don’t stress. A lot of the cPanel installations on the internet have cPanel’s auto-update functionality enabled, meaning that you may no longer be vulnerable without having to patch yourself. If you do not have this feature set up, please read this link for instructions on how to enable it.
As always, customers of our Attack Surface Management platform were the first to know when this vulnerability affected them. We continue to perform original security research in an effort to inform our customers about zero-day vulnerabilities.
You can read cPanel’s official advisory here.
Getting Familiar with cPanel’s codebase
cPanel has existed for as long as I have in this world (designed in 1996), for just over 27 years. It’s probably one of the oldest pieces of software we have ever audited at Assetnote. In order to perform our testing, we spun up a DigitalOcean droplet with the marketplace image for cPanel on Ubuntu. This was incredibly convenient and easy, cutting down our setup time significantly.
The historic nature of cPanel means that there are a number of paradigms and technologies that it leverages that aren’t necessarily modern. Namely, most of cPanel is written in Perl with some attack surface being Perl compiled to binaries.
When we initially looked at cPanel mid last year, we focused heavily on the binaries that can be accessed in the <span class="code_single-line">/cgi-sys/</span> directory on cPanel’s management ports. These binaries were Perl code that has been compiled to binaries which were intentionally supposed to be called remotely via HTTP requests. Understanding the logic of these binaries was difficult and while we found several avenues for exploitation, we found that mitigations had been built in that prevented us from successfully exploiting these potential issues.
Outside of these binaries inside this directory, we also noticed that cPanel’s core functionalities and web application are serviced through the <span class="code_single-line">cpsrvd</span> binary. This binary is listening on the following ports:
cPanel leverages Apache’s reverse proxy functionalities and the configuration for this can be found here: <span class="code_single-line">/etc/apache2/conf/httpd.conf</span>. This file provided us with a lot of clues and context around what to look for inside the cPanel codebase as there was a lot of proxying and script aliases that defined interesting attack surface:
The above is just a small excerpt of the <span class="code_single-line">httpd.conf</span> file. If you’re considering auditing cPanel we recommend going through all of the different proxy rules inside this file as a starting point.
Thankfully, cPanel does ship with a huge chunk of its source code, which can be obtained from a post-installation cPanel instance at the location <span class="code_single-line">/usr/local/cpanel/</span>. While this is also where most of the binaries exist, you can still understand some of the logic of cPanel through reading the libraries and perl code from this directory.
While the perl code inside that folder contains a huge number of clues as to how routing works, the source of truth is still the <span class="code_single-line">cpsrvd</span> binary, which is ultimately a compiled version of all of the perl. The source code found in the <span class="code_single-line">/usr/local/cpanel</span> directory did not seem like a complete picture of the true functionalities provided by cPanel. Nonetheless, we were grateful of this as it gave us enough context to find the XSS vulnerability.
Deconstructing Httpd.pm
While trying to understand the routing of cPanel, we came across <span class="code_single-line">Cpanel/Server/Handlers/Httpd.pm</span> which contained some very specific handling of certain paths. This logic allowed us to map out and understand some of the pre-authentication attack surface without having to understand the binaries.
The comments at the top of the file gave us a good overview of what this handled:
The following functionalities were found inside this Perl code:
- Handling subdomain/hostname based routing to certain services
- <span class="code_single-line">cpcalendars => 'proxy_cpcalendars_cpcontacts'</span>
- <span class="code_single-line">cpcalendars => 'proxy_cpcalendars_cpcontacts'</span>
- <span class="code_single-line">cpcontacts => 'proxy_cpcalendars_cpcontacts'</span>
- <span class="code_single-line">autodiscover => 'autodiscover'</span>
- <span class="code_single-line">autoconfig => 'autoconfig'</span>
- Handling static paths
- <span class="code_single-line">/img-sys/</span>
- <span class="code_single-line">/sys_cpanel/</span>
- Handling redirects for <span class="code_single-line">/cpanel</span>, <span class="code_single-line">/whm</span>, <span class="code_single-line">/webmail</span>
- Handling BoxTrapper requests <span class="code_single-line">/cgi-sys/bxd.cgi</span>
- Handling Dynamic DNS related functionality, specifically calls to <span class="code_single-line">/cpanelwebcall/</span>
In addition to <span class="code_single-line">Httpd.pm</span>, we also spent a significant amount of time on <span class="code_single-line">Cpanel/Server/Handlers/comet.pm</span> which handles websocket messages. There was a lot of interesting functionality that seemed like it could lead to an arbitrary file write, but during the time we had allocated for cPanel research, we were unsuccessful in finding a sink with any meaningful control.
Finding the Cross-Site Scripting
Inside <span class="code_single-line">Httpd.pm</span>, we can see the following snippet of code:
This meant that any path starting with <span class="code_single-line">/cpanelwebcall/</span> would be routed to <span class="code_single-line">_serve_cpanelwebcall</span>, along with the characters after the directory name.
The <span class="code_single-line">_serve_cpanelwebcall</span> function looked like this:
This led us to the function <span class="code_single-line">Cpanel::Server::WebCalls::handle</span> as the sink:
This leads to:
We can trace this back to <span class="code_single-line">Cpanel/Exception/cpsrvd/BadRequest.pm</span>. This is where the trail goes cold. Even though we have a lot of Perl source code available, this entire chain was not able to be traced end to end as we were missing the call to <span class="code_single-line">Httpd::ErrorPage</span>.
We worked out that the sink was in <span class="code_single-line">Cpanel::Server::Handlers::Httpd::ErrorPage</span> which we do have the source for, but we were unable to find the source code that initializes this Perl code. We suspect that this is embedded within the cPanel binary and hence why we were unable to pin point where this code was being called.
Digging into the <span class="code_single-line">Httpd::ErrorPage</span> code, we can see that it takes in a variable called <span class="code_single-line">message_html</span> which is the sink for this vulnerability. This variable is not sanitised in any way in vulnerable versions of cPanel.
Looking at the patch diff from the latest version of cPanel which has resolved this vulnerability, we can see that the following two lines were added to <span class="code_single-line">Cpanel/Server/Handlers/Httpd/ErrorPage.pm</span>:
Proof of Concept
Putting everything we learnt above together, we can come up with a simple proof of concept such as the one below:
Impact
The impact of this vulnerability is that we are able to execute arbitrary JavaScript, pre-authentication, on almost every port of a webserver using cPanel within its default setup.
This is because of the proxy rules discussed earlier in the blog post. Even on port 80 and 443, we are able to reach the <span class="code_single-line">/cpanelwebcall/</span> directory as it is being proxied to the cPanel management ports by Apache.
Because of this, an attacker can not only attack the management ports of cPanel but also the applications that are running on port 80 and 443.
Due to the fact that the cPanel management ports are vulnerable to this cross-site scripting attack, an attacker could leverage this vulnerability to hijack a legitimate user’s cPanel session.
Once acting on behalf of an authenticated user of cPanel, it is usually trivial to upload a web shell and gain command execution.
Remediation and Timelines
This vulnerability can be remediated by upgrading to any of the following cPanel versions or above:
- 11.109.9999.116
- 11.108.0.13
- 11.106.0.18
- 11.102.0.31
The timeline for disclosure can be found below:
- Jan 23rd, 2023: Disclosure of the XSS vulnerability to cPanel via <span class="code_single-line">security@cpanel.net</span>.
- Jan 23rd, 2023: Confirmation from cPanel that they have received the vulnerability and are investigating further.
- Feb 12th, 2023: Request for updates from Assetnote side
- Feb 13th, 2023: Vulnerability confirmed by cPanel and assigned <span class="code_single-line">SEC-669</span>. Targeted security fix release to follow in a few weeks.
- March 1st, 2023: Vulnerability fixed and public disclosure released on cPanel website.
cPanel were excellent to work with and remediated this issue within a reasonable time frame after we had disclosed this vulnerability to them.
Conclusion
cPanel has a vast attack surface and it needs more attention from the security researcher community. One of the big blockers during our research of cPanel was the binaries that had been compiled to Perl. We believe that there are more serious bugs yet to be found within these binaries, although, they are quite painful to work with from a reverse engineering perspective.
Our anaylsis of the <span class="code_single-line">cpsrvd</span> binary found that most endpoints were not accessible pre-authentication, however, there are plenty of binaries inside the <span class="code_single-line">/cgi-sys/</span> directory that could use more attention.
This was one of the first cases where we had reported a bug to a vendor that had a working and mostly default implementation of auto-updates for their software. This mitigation alone has protected a majority of cPanel websites from this vulnerability in the wild.
That being said, it is still possible to find a large number of cPanel websites that are still vulnerable to this as they did not have the auto-update feature enabled.
More Like This
Ready to get started?
Get on a call with our team and learn how Assetnote can change the way you secure your attack surface. We'll set you up with a trial instance so you can see the impact for yourself.