Pancakes 3 (2022) CTF

Ari Kalfus | Jan 29, 2022 min read

PancakesCon is an excellent community online conference that I wish to never see again. It first began as an impromptu, virtual hacker con in March 2020 as a result of the closure of all the in-person conferences. Now in its 3rd rendition as we enter the 3rd year of the pandemic, it continues to be an incredible demonstration of the compassion present in much of the Information Security community. That being said, it would be wonderful if we could vaccinate (for those who can), take precautions, and make our way out of this pandemic, ending the tradition of creating a virtual conference to replace the in-person events not currently possible. The conference is made up of 40-minute presentations where each talk includes introductory infosec material and introductory non-infosec hobby material. For example, in 2022 we had talks such as “what to look for in a manager, and pottery” and “delicious pretzels and devious packets.”

Oh, and there’s a CTF! This year, there was a jeopardy-style capture-the-flag competition with “networks to enumerate, boxes to root, and other surprises.” The CTF was open for roughly 8 hours and encouraged team participation. I participated without a team, and while I wasn’t able to dedicate a full 8 hours to the CTF, I made it to 3rd place in the first hour and ended up in 9th by the end of the day. With another 30 minutes, I would have gotten root on PWN-4, but so it goes!

One particularly excellent part of this CTF was that you were not provided with specific servers per challenge on the jeopardy board. Instead, we were given an OpenVPN connection file and the private network subnet range - 198.51.100.0/24. We had to discover live hosts on the network, identify to which challenge they belonged, and solve the challenges from there. There were a number of hosts with the exact same ports open and, after investigating the open ports on one of those hosts, I determined they were decoys or additional noise on the network to distract from the real challenge servers.

I leveraged nmap to enumerate the network:

nmap -sn 198.51.100.0/24
nmap -sS -T5 198.51.100.0/24

Once I discovered the live hosts, I typically ran the following on each:

nmap -sS -T5 -p- 198.51.100.0/24
nmapAutomator.sh -H 1908.51.100.X -t recon

I am a big fan of mind maps, and used Xmind while enumerating the network. I spent the first hour of the CTF enumerating the subnet, identifying hosts and ports, and generally information gathering. My mind map, at the end of the CTF, looked like this:

mind map

I’ll break down what I highlighted on each server as I step through them. In order to organize the servers, they are written out numerically and not by the order in which I solved them. My solve order was: NET-6, NET-1, PWN-4, PWN-3, NET-2. I had some progress on some of the other servers as well, but I neglected to take detailed enough notes, so I’m only talking about the ones I completed in this writeup.

NET

The NET-* servers did not involve any compromise of user systems or exploitation of the servers. They all required network enumeration.

NET-1

I am a big fan of nmapAutomator. It runs an nmap scan then auto-runs the typical protocol-specific enumeration/recon tools for the popular services. In this case, it caught the flag when scanning the 443/tcp port:

nmapAutomator net-1

This would have shown up in a regular nmap scan as well. I just so happened to capture it with the nmapAutomator output.

How I captured this in my mind map:

net-1 mindmap

NET-2

This is a server I had to come back to a couple hours into the CTF because I was using the wrong syntax or something and my initial enumeration of this server with onesixtyone wasn’t working. Clearly it should have, from the flag I eventually found.

The nmap scan revealed an open web server and a robots.txt file. robots.txt listed /another-flag.txt as a disallowed route. Going to that file returned the text It's not TCP this time. I re-ran nmap with the UDP scan flags:

nmap -sU --top-ports 50 198.51.100.146

and found 1 open port, 161/udp. 161 is - typically - the SNMP port. https://infinitelogins.com/2021/02/21/enumerating-snmp-for-pentesting-udp-ports-161-162/ is a useful site with common enumeration commands for SNMP. Using the following syntax, I received a dump of information in my terminal. I paged around until I noticed this flag.

snmpwalk -v2c -c public 198.51.100.146
snmpwalk output

How I captured this in my mind map:

net-2 mindmap

NET-6

The nmap scan for this server returned the open ports 22/tcp, 139/tcp, and 445/tcp. Port 139 is typically NetBIOS, and nbtscan confirmed this was the NET-6 host.

nbtscan net-6

Port 445 indicated that SMB was running, which is very interesting. smbclient is an FTP-like client to access SMB resources on a server. smbmap is another very useful tool to enumerate SMB shares.

smbclient null authentication

I don’t have any authentication credentials to NET-6, but let’s see if it will accept an anonymous connection - providing no username or password. It does! It looks like I have read-only access to the files share. I wonder what is in there?

net-6 smb flag

flag.txt looks very interesting! It contained our flag for this challenge.

How I captured this in my mind map:

net-6 mindmap

PWN

These servers required you to get a user and then a root flag. They were broken up into 2 challenges to score points on - e.g. “PWN-4 user,” “PWN-4 root.”

PWN-3

The nmap scan for this server revealed an open web server on port 8000/tcp. The robots.txt file disallowed entry to /fuel/. Well, let’s check that out. I was presented with a blog site. “Welcome to Fuel CMS” it said. Thanks! I said.

Navigating to the /fuel/login/ page, I guessed admin / admin and successfully logged into the CMS. I’ve successfully hosted a PHP webshell in scenarios such as this, but before I proceeded to exploit the server I wanted to make sure my information gathering was complete. If I dive too quickly into one path, I won’t become aware of alternatives.

https://www.exploit-db.com is an excellent resource when looking to determine whether a particular technology has exploitable vulnerabilities. On Kali Linux hosts, there is a command-line tool to search the Exploit-DB database called searchsploit. And speaking of alternative paths, searchsploit revealed that there were remote code execution (RCE) exploits against the version of Fuel CMS used on this site (1.4.1). Well, let’s use that.

fuel cms searchsploit

After modifying the url = "http://127.0.0.1:8881" line hard-coded into the script to point to the target system, I used the first exploit listed, https://www.exploit-db.com/exploits/47138, to get a user shell on the host as www-user.

fuel cms user shell

My shell commands were outputted within a PHP error inside HTML syntax. This is due to how this exploit script functions. I encourage you to look at the 47138 exploit-db link above and see if you can read how the script is executing.

I spawned a new TTY shell to begin gathering information on this host. My first goal was to get a user flag, followed by identifying how to escalate to root and retrieve the root flag. One of my first common enumeration steps is to see what else is running on the host. ps aux told me that I was almost certainly running inside a Docker container. (What else has an init script named entrypoint?) The hostname in my command line (www-data@40c422c94090) was another suspicious indicator of running inside a container.

ps aux

I also got the lay of the land inside www-data’s common directories, such as /var/www/html. Hey, may as well see what was going on inside /usr/local/entrypoint.sh, right? I found MySQL credentials and could access the database behind the Fuel CMS instance, but the only data of note was the admin user’s password hash, and I already guessed the password above. So nothing helpful here.

mysql creds

Another common enumeration step I use is to search for unusual SUID or SGID files.

find / -perm -g=s -o -perm -u=s -type f 2>/dev/null

The SUID bit is a special permission that allows other users to run an executable with the owner’s privileges. Therefore, if I encounter an executable owned by root with the SUID bit set, invoking that executable as www-data will run my command as if I was root. If there is a vulnerability or misconfiguration in the executable, I might be able to leverage that into a root shell.

My find command returned one atypical SUID file - /var/www/html/fuel/install/helper. This executable prompted for a command and seemed to run whatever I gave it. With the SUID bit set, it was running the command as root. helper bash elevated me to a root shell :)

pwn3 container root shell

There was a flag I can now access. Hold on, it was invalid as the answer to the PWN-3 root challenge. Oh right… I was still in a Docker container. I entered the flag in the PWN-3 user challenge and was rewarded with points.

Now I needed to break out of the container to become root on the host. https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/ was a really useful article describing a method to access host filesystem resources from a container run with --privileged. One way to check if you are in a privileged container is to see whether the contents of the typical filesystem block names (e.g. sda) exist under /dev. From there, you can mount /dev/sda1, or whatever is there, to an empty folder in your docker container to gain full access to the filesystem contents of the host.

However, I didn’t think of that during the challenge :) I leveraged Trail of Bit’s excellent article to write the root flag into the container. I learned some stuff and it was therefore useful, so that’s good!

Following the Trail of Bits article, I used the following cmd script to expose the root flag into the container:

trailofbits docker escape

This created an /output file inside the container that I could read. I quickly cleaned up after myself as these files would have exposed the root flag to other players who only had www-data access inside the container.

How I captured this in my mind map:

pwn-3 mind map

PWN-4

This server tricked me up for a long time. I saw the vulnerable server early and what the likely vulnerability was, but my initial exploitation attempts failed and I stopped to attempt other servers. Near the end of the CTF, a hint was provided for this server confirming my initial exploitation attempts. Re-attempting the “basic” exploit for the user access vulnerability worked this time, naturally. I ran out of time in the user shell and wasn’t able to escalate my access to root and finish the PWN-4 root challenge. I’m pretty confident I knew what the escalation path was, and would likely have solved it with another 15 minutes! Oh well. That’s how CTFs go.

The nmap scan for this server revealed a lighthttp web server running on port 80. I began exploring the web server. The robots.txt file had a disallow listing for /maint. I navigated there and discovered directory listing revealing some very interesting files.

pwn-4 robots.txt pwn-4 exposed id_rsa

Not only was the user flag revealed in flag.txt, but I had someone’s public and private SSH key. Not just anyone’s SSH key, but the root user!

root id_rsa pub

This seemed too easy…

Sure enough, ssh -v -i id_rsa [email protected] showed I successfully authenticated to the PWN-4 server as root. I was shown a banner message, and then the SSH connection immediately closed. Notably, and unfortunately I did not grab a screenshot, but the SSH banner before the connection closed disclosed that the version of bash running on the system was 4.3.8(1). Googling “bash 4.3.8 exploit” returned articles about Shellshock. This was very promising, but how could I trigger the shellshock vulnerability through my SSH connection before the connection was immediately terminated? I used ssh’s -t flag and executed bash through a shellshock exploit that then called a Bash reverse shell back to my machine.

shellshock ssh

This connected back to my machine and I got a shell on the server.

busybox chroot jail

However, this was no normal shell environment. I ran out of time here, but I am reasonably certain I was in a chroot jail. Notably, /proc didn’t exist. This may have helped me escape the jail, but by this point the CTF had ended. https://filippo.io/escaping-a-chroot-jail-slash-1/

How I captured this in my mind map:

pwn-4 mindmap

Wrap-Up

This was a really enjoyable (and often frustrating!) CTF. I had not competed in a CTF where you had to enumerate the subnet before you could locate the challenge hosts. That was a lot of fun. I heard there was another NET challenge server that no one discovered, but was discoverable from one of the PWN servers. Sniffing network traffic from that host would have revealed another server pinging every few minutes. Unfortunately, I didn’t discover it, but it highlights how fun, thorough, and challenging this format for a CTF can be.

I hope to attend another PancakesCon next year, for both the talks and the CTF! Although, if I’m being honest, I’d rather the pandemic end than the community throw together another virtual PancakesCon in 2023.

comments powered by Disqus