TryHackMe's Advent of Cyber 2023 - Side Quest 3 - Frosteau Busy with Vim - Writeup

 2023-12-16

Hiya ! Time for the Side Quest 3 writeup ! This challenge is named Frosteau Busy with Vim and is rated insane. If you want to skip the part where I explain how to get the QR code, click here.

Link to the challenge : https://tryhackme.com/room/busyvimfrosteau

Link to the meta-article about the side quests : https://eyexion.fr/posts/thm_aoc_2023_meta/

Crop away the secret (or don’t)

The QR code was hidden in the day 11 of the Advent of Cyber. After using a misconfigured Active Directory and abuse the rights of a user to access the Adaministrator's data, we were left with a file chatlog.html and a directory chatlog-files leading us to have the following page :

Chat logs

So we can see that we have in our hands a cropped image from the Snip & Sketch tool in Windows 10. Now, I was lucky to already have encountered this sort of challenge in a CTF, so I directly knew what to do.

Earlier this year, a vulnerability called Acropalypse allowed anyone to go back to the un-cropped image if it was cropped using various tools, including the Snip & Sketch in Windows 10. What these tools did was only add an IEND field in the middle of the data of png file, leaving the rest of the image data as is.

It is thus possible to revert the cropping using various tools including https://acropalypse.app/. Unofortunalty (and it was the same with the previous challenge), this website did not function. I used https://github.com/frankthetank-music/Acropalypse-Multi-Tool instead. This gives us the following result with the format 2560x1080 based on the second screenshot in the files :

Uncropped image

We get the QR code ! Really fun idea by the way, and cool way to use recent vulnerabilities !

Statement (of the Side Quest)

The actual challenge gives us the objective to ice Frosteau's machine 🧊, nothing more. During the challenge, an unintended solution was found and fixed, and a hint was given for us to find the third flag. There were 4 + 1 flags to find without any indications, but the challenge “flowed” and the flags were in “classic” locations, only needed to reach them somehow !

Network scan and services

A simple SYN scan gave us the following result :

└─$ sudo nmap -sS -p1-65365 10.10.20.11
[sudo] password for kali: 
Starting Nmap 7.94SVN ( https://nmap.org ) at 2023-12-17 16:03 EST
Nmap scan report for 10.10.20.11
Host is up (0.034s latency).
Not shown: 65359 closed tcp ports (reset)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8065/tcp open  unknown
8075/tcp open  unknown
8085/tcp open  unknown
8095/tcp open  unknown

So as we can see, we have a lot of ports open, trying to connect to each of them gives us the following results

  • Port 80 hosts a webpage with a 405 Method Not Allowed in GET, POST, PUT …
  • Port 8065 is open but does not seem to run anything I know. Connecting to it with netcat gives us the response Ubuntu 22.04.3 LTS and the connection closes immediately
  • Port 8075 responds with 220 Operation successful which shows than an FTP server is listening
  • Port 8085 connects to a remote Vim session ! We can type commands, open files … (see after)
  • Port 8095 is the same as 8085 but for Nano (they needed to please everyone !)

So a lot of things, but we like that 🎉.

Flags To Pocket (FTP)

Ok, so first thing we try is to connect to the FTP server anonymously and, well it works ! So we get this :

└─$ ftp 10.10.20.11 -P 8075 -a -v
Connected to 10.10.20.11.
220 Operation successful
230 Operation successful
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 Operation successful
150 Directory listing
total 8132
-rw-r--r--    1 0        0             3010 Nov  5 18:49 FROST-2247-SP.txt
-rw-r--r--    1 0        0             3211 Nov  5 18:50 YETI-1125-SP.txt
-rw-r--r--    1 0        0               24 Nov  5 19:06 flag-1-of-4.txt
-rw-r--r--    1 0        0               12 Nov  5 19:07 flag-2-of-4.sh
-rw-r--r--    1 0        0          2127524 Nov  5 18:54 frostling_base.png
-rw-r--r--    1 0        0          2305908 Nov  5 18:54 frostling_five.png
-rw-r--r--    1 0        0          1589463 Nov  5 18:54 yeti_footage.png
-rw-r--r--    1 0        0          2277409 Nov  5 18:54 yeti_mugshot.png
226 Operation successful
ftp> get flag-1-of-4.txt
local: flag-1-of-4.txt remote: flag-1-of-4.txt
200 Operation successful

So we get the first flag ! And we have a curious looking second flag containing a bash script with only echo $FLAG2 inside, so an environment variable.

Anyway, we can also upload files in the directory with FTP, that will come in handy later.

Vim > all

Now back to Vim. We can connect to the Vim session using netcat. We then need to be able to send our signals (escape, Ctrl-c,…) to the remote machine. To do that, we only need to put the process in background (Ctrl-z) and execute stty raw -echo; fg. We can now do whatever we want !

So the first thing we try is using shell commands like :!id but very quickly we notice that we do not have a working shell executable ! The default $SHELL variable is set to /tmp/sh. Trying to set it to /bin/sh & co does not function. Nonetheless, we can still explore the file system with :e / and see what we’re dealing with.

Quickly we see that we are in a Docker container (presence of /.dockerenv). We also have access to a lot of directories, but nothing interesting to open. But as we explore, we can notice a file /etc/busybox which is a known shell executable embedding a lot of common commands directly in it (used in Docker a lot). But do not have the right to execute it (nor see it).

In the Vim instance we can use the :py3 command to run python commands too. It did not help me solve this challenge, but maybe it had a use. Also, we notice that the FTP root directory is located in /tmp/ftp.

Uploading a shell to the machine

So this is where the hint from the third flag comes in handy. We can indeed upload to the machine a busybox executable, and use it ! But we have one problem. busybox does not support the -c and vim uses the $SHELL -c <cmd> format when using a command with :!. So I could not just upload the busybox executable and run it. So I did a very messy and disgusting thing but hey it worked. There was probably a way to use python or even nano but hey I found this randomly.

So basically I uploaded my own /bin/sh from my VM (same architecture) knowing that I would not get anything but I only wanted a way to execute busybox afterwards (using :py3 could have probably done the job as well). After uploading my /bin/sh via FTP, I did the following

  • Open in Vim the file /tmp/ftp/sh
  • Save it in /tmp/sh with :w /tmp/sh
  • Set it executable with :call setfperm("/tmp/sh","rwxrwxrwx")
  • Run :!/tmp/sh

And I have a “SHELL”, with almost no commands but that is enough. (I have the really basic ones like cd or pwd, built-in commands). I can also check out the second flag with $FLAG2 in the shell.

Fake shell Now, I can perform the same steps but uploading a busybox standalone executable ! So using https://busybox.net/downloads/binaries/1.35.0-x86_64-linux-musl/busybox I get a usable busybox executable. So upload, save in /tmp/busybox, set executable and run /tmp/busybox ash in the previous shell we opened and we have a decent shell !

Busybox shell

As you can see, we need to add the prefix busybox before all commands but it works.

Privilege escalation in the container

So now the challenge becomes more classic. After looking around a little bit, we see a juicy process running as root :

Root process telnetd

So that explains the weird stuff we had on port 8065 before ! So now all we have to do is move the file /tmp/busybox we have to /usr/frosty/sh and connect to port 8065 of the machine, we should be root in the container. Because it’s fun you get a GIF.

Root in docker

We can get the third flag in /root after that in the root shell.

Docker escape 101

So now onto the easiest part of the challenge IMO. The natural next step after being root in a Docker container is to try and escape from it to access the host's rootfs.

In my case the first thing I check are mountable devices, it is not uncommon in “easy” Docker challenges to be able to mount the hosts rootfs. After checking the /dev directory, we can see the juicy looking /dev/root device. So of course I try to mount it, and to my surprise I got into the host’s rootfs. Here is a GIF to sum it up. But basically you only need to mount /dev/root and access the flags in /tmp/mount/root if your mount point is /tmp/mount.

Docker escape

Et voilà, you even get a 2 flags for 1 deal.

Conclusion

So overall an original first part of the challenge, I personally found it not too hard and rather “classic” with some twists. I did not use the website running on port 80 nor the nano service, there are probably other ways to get the flags I guess. But overall enjoyable, curious to read other writeups on this one.

Side note, I really think my way of solving it is disgusting with the /bin/sh, there has to be a more elegant way to do it but was proud to find something randomly so 🤡.