Writeup of the covfefe CTF
Capture the Flag (CTF) challenges offer a great opportunity to practice hacking skills in a controlled and legal environment. One of the most common places to look for such challenges is vulnhub.com. Vulnhub offers Virtual Machines that are configured in an insecure way, so that the user can learn new techniques.
A couple of days ago I stumbled upon the covfefe machine.
After setting up my environment I started with the initial recon phase. The recon phase is used to find as much information about the system as possible. This is done in the hope that outdated software is used which can be used for easy exploitation with known vulnerabilities.
Usually this is done with nmap. I used the command
nmap -A -p- 192.168.56.101. This scans all the ports and fingerprints them. So it's easy to find out what services and which versions are running.
The scan reveals the following:
root@kali:~# nmap -A 192.168.56.101 Starting Nmap 7.60 ( https://nmap.org ) at 2017-11-08 16:10 CET Nmap scan report for 192.168.56.101 Host is up (0.00028s latency). Not shown: 997 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.4p1 Debian 10 (protocol 2.0) | ssh-hostkey: | 2048 d0:6a:10:e0:fb:63:22:be:09:96:0b:71:6a:60:ad:1a (RSA) | 256 ac:2c:11:1e:e2:d6:26:ea:58:c4:3e:2d:3e:1e:dd:96 (ECDSA) |_ 256 13:b3:db:c5:af:62:c2:b1:60:7d:2f:48:ef:c3:13:fc (EdDSA) 80/tcp open http nginx 1.10.3 |_http-server-header: nginx/1.10.3 |_http-title: Welcome to nginx! 31337/tcp open http Werkzeug httpd 0.11.15 (Python 3.5.3) | http-robots.txt: 3 disallowed entries |_/.bashrc /.profile /taxes |_http-server-header: Werkzeug/0.11.15 Python/3.5.3 |_http-title: 404 Not Found MAC Address: 08:00:27:CD:38:F1 (Oracle VirtualBox virtual NIC) Device type: general purpose Running: Linux 3.X|4.X OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4 OS details: Linux 3.2 - 4.8 Network Distance: 1 hop Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE HOP RTT ADDRESS 1 0.28 ms 192.168.56.101 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 11.75 seconds
What do we make of it? There are 3 services running, an ssh service on port 22, a web server on port 80 and another service that also looks like a web server on port 31337. Let's first try the easy way and connect to the web server. When we fire up a browser and enter the IP address, we see that Nginx is set up, but there is no content. Maybe dirbuster can help here? Dirbuster is a program that enumerates over a wordlist of well know folders and tries to connect to them. But this was to no avail.
Our next step is the ssh port. Connecting via:
ssh 192.168.56.101 just shows us, that we need a key to connect here. Bruteforcing is not even an option.
Our last hope is port 31337. We already know about 3 folders from the nmap scan: /.bashrc, /.profile and /taxes. The first two only contain scripts which we put aside for now. The latter however gives us our first flag :-)
First flag down, 2 to go! Let's fire up dirbuster again... Success! We find a /.ssh folder. On a regular machine ssh keys are stored in this folder, it could not be, could it?! But we are lucky, someone left his key pair and the authorized_keys file for everyone to see.
Looking at the contents of authorized_keys and the public key we find our username: "simon". With this new information we can try ssh again, this time we have a key. "ssh -i id_rsa email@example.com"(Remember ssh keys need the right set of permissions to be allowed in, 700 is the charm here). Still no luck now we need a password to continue.
One of the most well known password cracking tools is "john the ripper" or "john" for short. On my kali distro I also found the tool "johnny" which is basically a GUI for john. Starting up johnny gives us the advantage that we do not have to convert the key file to the right format. While johnny is cracking we can get another Mate to refuel for the last part of the CTF.
Now that we have the password remember "Han was the only one who shoot" and lets login. Success! We are in, but not done yet, still 2 flags to capture. Investigating the home folder of simon does not yield any new information. Let us snoop around a little bit and run an enumeration script. An enumeration script looks around in the hope of finding more vulnerable stuff, for this task I used the highon.coffee script. This gives us 2 interesting findings. There is a SUID binary and the "/root" folder is readable by everyone. Executing the binary asks us for our name. Is "simon" the answer? Apparently it is not, what about "Simon". Bullseye, another hint at the root folder, time to look at it. Switching to it shows us 2 files, a flag that we cannot read and some C Code. The code gives us the second flag and also some hints on how to proceed. Looks like we need to create a buffer overflow to get root.
Firing up "read_message" again and messing around with it, using the newly acquired knowledge, it is easy to mess around with the program by just entering more than 20 characters. This at least destroys the call to the "/usr/local/sbin/message". How can we use this to our advantage? Well obviously by creating a shell. Calling a shell directly does not work, we still only get Simons' rights. Will creating a reverse shell work? We put a reverse shell script in the "/tmp" folder and listen on our attacker machine via:
nc -vl 80. We get our reverse shell but still only Simons' rights... What is the problem here? The program has the SUID flag set and is owned by root.
After doing some research we learn that the SUID bit does not work on shell scripts. We need a workaround, how about a program that uses the SUID part and executes our script? Unfortunately the VM does not offer gcc, so we need to compile for this i686 architecture. No problem lets just set up another VM and compile a program which sets the wanted user id and then calls our script.
So let us listen on our attacker machine and execute the script via our compiled binary and cross our fingers. Aaand SUCCESS! Entering "id" on our reverse shell gives us:
With these rights we can read the last flag and are done with this machine.
What is the takeaway here? SUID does not work on shell scripts and always needs a workaround.