Joomla - Discovery and Enumeration
Joomla, released in August 2005 is another free and open-source CMS used for discussion forums, photo galleries, e-Commerce, user-based communities, and more. It is written in PHP and uses MySQL in the backend. Like WordPress, Joomla can be enhanced with over 7,000 extensions and over 1,000 templates. There are up to 2.5 million sites on the internet running Joomla. Here are some interesting statistics about Joomla:
- Joomla accounts for 3.5% of the CMS market share
- Joomla is 100% free and means "all together" in Swahili (phonetic spelling of "Jumla")
- The Joomla community has close to 700,000 users in its online forums
- Joomla powers 3% of all websites on the internet, nearly 25,000 of the top 1 million sites worldwide (just 10% of the reach of WordPress)
- Some notable organizations that use Joomla include eBay, Yamaha, Harvard University, and the UK government
- Over the years, 770 different developers have contributed to Joomla
Joomla collects some anonymous usage statistics such as the breakdown of Joomla, PHP and database versions and server operating systems in use on Joomla installations. This data can be queried via their public API.
Querying this API, we can see over 2.7 million Joomla installs!
m4cc18@htb[/htb]$ curl -s https://developer.joomla.org/stats/cms_version | python3 -m json.tool
{
"data": {
"cms_version": {
"3.0": 0,
"3.1": 0,
"3.10": 3.49,
"3.2": 0.01,
"3.3": 0.02,
"3.4": 0.05,
"3.5": 13,
"3.6": 24.29,
"3.7": 8.5,
"3.8": 18.84,
"3.9": 30.28,
"4.0": 1.52,
"4.1": 0
},
"total": 2776276
}
}
Discovery/Footprinting
Let's assume that we come across an e-commerce site during an external penetration test. At first glance, we are not exactly sure what is running, but it does not appear to be fully custom. If we can fingerprint what the site is running on, we may be able to uncover vulnerabilities or misconfigurations. Based on the limited information, we assume that the site is running Joomla, but we must confirm that fact and then figure out the version number and other information such as installed themes and plugins.
We can often fingerprint Joomla by looking at the page source, which tells us that we are dealing with a Joomla site.
m4cc18@htb[/htb]$ curl -s http://dev.inlanefreight.local/ | grep Joomla
<meta name="generator" content="Joomla! - Open Source Content Management" />
<SNIP>
The robots.txt file for a Joomla site will often look like this:
# If the Joomla site is installed within a folder
# eg www.example.com/joomla/ then the robots.txt file
# MUST be moved to the site root
# eg www.example.com/robots.txt
# AND the joomla folder name MUST be prefixed to all of the
# paths.
# eg the Disallow rule for the /administrator/ folder MUST
# be changed to read
# Disallow: /joomla/administrator/
#
# For more information about the robots.txt standard, see:
# https://www.robotstxt.org/orig.html
User-agent: *
Disallow: /administrator/
Disallow: /bin/
Disallow: /cache/
Disallow: /cli/
Disallow: /components/
Disallow: /includes/
Disallow: /installation/
Disallow: /language/
Disallow: /layouts/
Disallow: /libraries/
Disallow: /logs/
Disallow: /modules/
Disallow: /plugins/
Disallow: /tmp/
We can also often see the telltale Joomla favicon (but not always). We can fingerprint the Joomla version if the README.txt file is present.
m4cc18@htb[/htb]$ curl -s http://dev.inlanefreight.local/README.txt | head -n 5
1- What is this?
* This is a Joomla! installation/upgrade package to version 3.x
* Joomla! Official site: https://www.joomla.org
* Joomla! 3.9 version history - https://docs.joomla.org/Special:MyLanguage/Joomla_3.9_version_history
* Detailed changes in the Changelog: https://github.com/joomla/joomla-cms/commits/staging
In certain Joomla installs, we may be able to fingerprint the version from JavaScript files in the media/system/js/ directory or by browsing to administrator/manifests/files/joomla.xml.
m4cc18@htb[/htb]$ curl -s http://dev.inlanefreight.local/administrator/manifests/files/joomla.xml | xmllint --format -
<?xml version="1.0" encoding="UTF-8"?>
<extension version="3.6" type="file" method="upgrade">
<name>files_joomla</name>
<author>Joomla! Project</author>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<copyright>(C) 2005 - 2019 Open Source Matters. All rights reserved</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>3.9.4</version>
<creationDate>March 2019</creationDate>
<SNIP>
The cache.xml file can help to give us the approximate version. It is located at plugins/system/cache/cache.xml.
Enumeration
Let's try out droopescan, a plugin-based scanner that works for SilverStripe, WordPress, and Drupal with limited functionality for Joomla and Moodle.
We can clone the Git repo and install it manually or install via pip.
m4cc18@htb[/htb]$ sudo pip3 install droopescan
Collecting droopescan
Downloading droopescan-1.45.1-py2.py3-none-any.whl (514 kB)
|████████████████████████████████| 514 kB 5.8 MB/s
<SNIP>
Once the installation is complete, we can confirm that the tool is working by running droopescan -h.
m4cc18@htb[/htb]$ droopescan -h
usage: droopescan (sub-commands ...) [options ...] {arguments ...}
|
___| ___ ___ ___ ___ ___ ___ ___ ___ ___
| )| )| )| )| )|___)|___ | | )| )
|__/ | |__/ |__/ |__/ |__ __/ |__ |__/|| /
|
=================================================
commands:
scan
cms scanning functionality.
stats
shows scanner status & capabilities.
optional arguments:
-h, --help show this help message and exit
--debug toggle debug output
--quiet suppress all output
Example invocations:
droopescan scan drupal -u URL_HERE
droopescan scan silverstripe -u URL_HERE
More info:
droopescan scan --help
Please see the README file for information regarding proxies.
We can access a more detailed help menu by typing droopescan scan --help.
Let's run a scan and see what it turns up.
m4cc18@htb[/htb]$ droopescan scan joomla --url http://dev.inlanefreight.local/
[+] Possible version(s):
3.8.10
3.8.11
3.8.11-rc
3.8.12
3.8.12-rc
3.8.13
3.8.7
3.8.7-rc
3.8.8
3.8.8-rc
3.8.9
3.8.9-rc
[+] Possible interesting urls found:
Detailed version information. - http://dev.inlanefreight.local/administrator/manifests/files/joomla.xml
Login page. - http://dev.inlanefreight.local/administrator/
License file. - http://dev.inlanefreight.local/LICENSE.txt
Version attribute contains approx version - http://dev.inlanefreight.local/plugins/system/cache/cache.xml
[+] Scan finished (0:00:01.523369 elapsed)
As we can see, it did not turn up much information aside from the possible version number. We can also try out JoomlaScan, which is a Python tool inspired by the now-defunct OWASP joomscan tool. JoomlaScan is a bit out-of-date and requires Python2.7 to run. We can get it running by first making sure the bs4 dependency is installed.
m4cc18@htb[/htb]$ python2 -m pip install bs4
While a bit out of date, it can be helpful in our enumeration. Let's run a scan.
m4cc18@htb[/htb]$ python2 joomlascan.py -u http://dev.inlanefreight.local
-------------------------------------------
Joomla Scan
Usage: python joomlascan.py <target>
Version 0.5beta - Database Entries 1233
created by Andrea Draghetti
-------------------------------------------
Robots file found: > http://dev.inlanefreight.local/robots.txt
No Error Log found
Start scan...with 10 concurrent threads!
Component found: com_actionlogs > http://dev.inlanefreight.local/index.php?option=com_actionlogs
On the administrator components
Component found: com_admin > http://dev.inlanefreight.local/index.php?option=com_admin
On the administrator components
Component found: com_ajax > http://dev.inlanefreight.local/index.php?option=com_ajax
But possibly it is not active or protected
LICENSE file found > http://dev.inlanefreight.local/administrator/components/com_actionlogs/actionlogs.xml
LICENSE file found > http://dev.inlanefreight.local/administrator/components/com_admin/admin.xml
LICENSE file found > http://dev.inlanefreight.local/administrator/components/com_ajax/ajax.xml
Explorable Directory > http://dev.inlanefreight.local/components/com_actionlogs/
Explorable Directory > http://dev.inlanefreight.local/administrator/components/com_actionlogs/
Explorable Directory > http://dev.inlanefreight.local/components/com_admin/
Explorable Directory > http://dev.inlanefreight.local/administrator/components/com_admin/
Component found: com_banners > http://dev.inlanefreight.local/index.php?option=com_banners
But possibly it is not active or protected
Explorable Directory > http://dev.inlanefreight.local/components/com_ajax/
Explorable Directory > http://dev.inlanefreight.local/administrator/components/com_ajax/
LICENSE file found > http://dev.inlanefreight.local/administrator/components/com_banners/banners.xml
<SNIP>
While not as valuable as droopescan, this tool can help us find accessible directories and files and may help with fingerprinting installed extensions. At this point, we know that we are dealing with Joomla 3.9.4. The administrator login portal is located at http://dev.inlanefreight.local/administrator/index.php. Attempts at user enumeration return a generic error message.
Warning
Username and password do not match or you do not have an account yet.
The default administrator account on Joomla installs is admin, but the password is set at install time, so the only way we can hope to get into the admin back-end is if the account is set with a very weak/common password and we can get in with some guesswork or light brute-forcing. We can use this script to attempt to brute force the login.
m4cc18@htb[/htb]$ sudo python3 joomla-brute.py -u http://dev.inlanefreight.local -w /usr/share/metasploit-framework/data/wordlists/http_default_pass.txt -usr admin
admin:admin
And we get a hit with the credentials admin:admin. Someone has not been following best practices!
Exercise
TARGET: 10.129.42.195
vHosts needed for these questions:
app.inlanefreight.local
Challenge 1
Fingerprint the Joomla version in use on http://app.inlanefreight.local (Format: x.x.x)
Since this is a Joomla module, I will assume Joomla is being used as their CMS in this app. Now to fingerprint its version I will use the techniques showed in this section in order, starting by reading the README.txt file.
┌──(macc㉿kaliLab)-[~/htb/attacking_common_apps]
└─$ curl -s http://app.inlanefreight.local/README.txt | head -n 5
1- What is this?
* This is a Joomla! installation/upgrade package to version 3.x
* Joomla! Official site: https://www.joomla.org
* Joomla! 3.10 version history - https://docs.joomla.org/Special:MyLanguage/Joomla_3.10_version_history
* Detailed changes in the Changelog: https://github.com/joomla/joomla-cms/commits/3.10-dev
- With this we know the overall version is 3.10, but we are still missing one digit.
Next we can check the administrator/manifests/files/joomla.xml file and see if it has a more specific version:
┌──(macc㉿kaliLab)-[~/htb/attacking_common_apps]
└─$ curl -s http://app.inlanefreight.local/administrator/manifests/files/joomla.xml | xmllint --format -
Output:
<?xml version="1.0" encoding="UTF-8"?>
<extension version="3.6" type="file" method="upgrade">
<name>files_joomla</name>
<author>Joomla! Project</author>
<authorEmail>admin@joomla.org</authorEmail>
<authorUrl>www.joomla.org</authorUrl>
<copyright>(C) 2019 Open Source Matters, Inc.</copyright>
<license>GNU General Public License version 2 or later; see LICENSE.txt</license>
<version>3.10.0</version>
<creationDate>August 2021</creationDate>
<description>FILES_JOOMLA_XML_DESCRIPTION</description>
<scriptfile>administrator/components/com_admin/script.php</scriptfile>
<update>
Note the output contains:
<version>3.10.0</version>
- This is probably it but I will keep going just for completion
The next thing we can try is using droopescan. Since it is kind of a deprecated tool I had to do some stuff for it to work:
# Activating a pip environment
┌──(macc㉿kaliLab)-[~/htb/attacking_common_apps]
└─$ python3 -m venv myenv
┌──(macc㉿kaliLab)-[~/htb/attacking_common_apps]
└─$ source myenv/bin/activate
# Cloning the repo, cd into it, and installing requirements.txt
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps]
└─$ git clone https://github.com/SamJoan/droopescan.git
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps]
└─$ cd droopescan
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps/droopescan]
└─$ pip install -r requirements.txt
# Tried it (1)
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps/droopescan]
└─$ ./droopescan -h
# Error: from imp import reload # pragma: no cover
^^^^^^^^^^^^^^^^^^^^^^
# Installed the zomnbie-imp (since imp was removed in python3.11)
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps/droopescan]
└─$ pip install zombie-imp
# Tried it (2)
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps/droopescan]
└─$ ./droopescan scan --help
from distutils.util import strtobool
ModuleNotFoundError: No module named 'distutils'
# Manually isntall 'setuptools<81' (includes disutils)
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps/droopescan]
└─$ pip install 'setuptools<81'
# Finally worked
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps/droopescan]
└─$ ./droopescan scan --help
usage: droopescan (sub-commands ...) [options ...] {arguments ...}
The command I will use is the same as the one shown in this module:
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps/droopescan]
└─$ droopescan scan joomla --url http://app.inlanefreight.local/
Basically the same output:
[+] Possible version(s):
3.10.0-alpha1
[+] Possible interesting urls found:
Detailed version information. - http://app.inlanefreight.local/administrator/manifests/files/joomla.xml
Login page. - http://app.inlanefreight.local/administrator/
License file. - http://app.inlanefreight.local/LICENSE.txt
Version attribute contains approx version - http://app.inlanefreight.local/plugins/system/cache/cache.xml
[+] Scan finished (0:00:01.418190 elapsed)
- Same version as in
administrator/manifests/files/joomla.xmlso that must be it.
flag: 3.10.0
Challenge 2
Find the password for the admin user on http://app.inlanefreight.local
Our droopscan scan already tells us:
Login page. - http://app.inlanefreight.local/administrator/
Therefore I will now use the script (joomla-brute.py) shown in this section to try to bruteforce the admin password. To install it I just cloned the repo and cded into it:
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps]
└─$ git clone https://github.com/ajnik/joomla-bruteforce.git
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps]
└─$ cd joomla-bruteforce
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps/joomla-bruteforce]
└─$ ls
joomla-brute.py README.md test.py
I will then run the following command to start the password bruteforcing "attack":
┌──(myenv)─(macc㉿kaliLab)-[~/htb/attacking_common_apps/joomla-bruteforce]
└─$ sudo python3 joomla-brute.py -u http://app.inlanefreight.local -w /usr/share/metasploit-framework/data/wordlists/http_default_pass.txt -usr admin
admin:turnkey
- Note we are using a kali built-in wordlist:
/usr/share/metasploit-framework/data/wordlists/http_default_pass.txt - Note also that we are targeting the
adminuser account
flag: turnkey