Sunshine CTF 2019 Write-up

George O
George O
Apr 15, 2019 · 9 min read

At the end of March this year, Hack@UCF released a CTF in collaboration with BSides Orlando 2019. Our team ended up coming 13th, narrowly missing out on a top 10 spot. You can find the homepage for this CTF here.

In this write-up, I’m only going to go over the challenges that I solved during the competition, going from what I found to be the easiest to the hardest.

Misc: Middle Ocean (75)

In this challenge, we were given a text file with the following contents:

After a quick bit of Googling, I found that these were plus codes. However, they all pointed to different oceans/deserts with little other information:

Google Maps results for each plus code.

I decided to convert them to lat/long coordinates to help make sense of the data using this website. These mapped out like so:

We can easily notice that these values are all within the ASCII range. Decoding them with CyberChef reveals the flag: “SUN{M495-f4n!}

Forensics: Golly Gee Willikers (100)

In this challenge, we were given another txt file with the following contents (download here):

Since the first line seems to be the only unique one, I Googled it and found a page detailing the RLE file format. The RLE file format is designed to store sequences for cell automation algorithms. The “B3/S23” rule in particular details Conway’s Game of Life templates.

I found a website in which you could import these templates, and loaded our one:

https://copy.sh/life/

We have almost every character available, but no flag. I then decided to find out what each character in the file meant. The official conwaylife.com wiki detailed each in detail.

  • b: Dead cell
  • o: Alive cell
  • $: End of line
  • <runcount>: Number of iterations for a combination (i.e. 3bo)
  • !: End of file

The key part of this wiki page is the following:

Anything after the final ! is ignored. It used to be common to put comments here (starting on a new line), but the usual method for adding comments is now by means of #C lines (see below).

In our RLE, there are two “!”s present. I removed the second one, and reran the script:

We now have the flag: “sun{th1s_w0nt_last}”!

Scripting: TimeWarp (50)

Let’s netcat in and see what happens:

When we put in a number (123), we get told another that we were supposed to put (39):

Let’s now put in the correct number:

We just just asked for another number. Essentially, we had to input the incorrect number at least once to find out the correct one.

I wrote a really messy script to run through these answers and eventually find the flag, as shown below:

It doesn’t actually stop when the flag is found, so you’ve got to be looking out for it. After around 300 iterations (maybe 45 mins of runtime), the flag is finally returned:

I later discovered that this challenge was intended to be completed by finding the seed from the challenge description, and calculating the sequence from there. Either way, this works :)

Crypto: 16-bit-AES (100)

Connecting to this server presents us with the following:

Let’s add some text:

So it looks like we have to work out the key, so that we can encrypt the given data. I connected a few times and verified that the key is the same in each session. Just like before, we needed a script to do the heavy work for us:

Since the key is only 16 bits, we find the correct key in around a second:

The key is therefore “fL” (repeated 8 times as padding). We can encrypt any given string with this, and receive the flag:

sun{Who_kn3w_A3$_cou1d_be_s0_vulner8ble?}

One of my teammates pointed out after the competition ended that we could have just opened another session and used that to encrypt any given plaintext… But I guess that would be less interesting.

Web: WrestlerBook (100)

We can visit the website, and see the following:

Simple SQL injection with ‘ OR 1=1 — # — bypasses the login form, but doesn’t give us anything else:

I then started enumerating the database via UNION injection. To begin with, I had to work out how many columns were in the current table for the UNION stuff to work. This can be done by constructing different ORDER BY queries until no errors are found.

Therefore, the table must have 8 columns. We can verify this with a simple SELECT/UNION injection:

Let’s now start enumerating the database. We know that it’s SQLite 3 (as the error messages mentioned), so I referred to this SQLite cheat sheet.

We can perform table name enumeration like so:

However, this only seemed to show one result. I looked into SQLite grouping, and found that we can use group_concat to concatenate all results into one:

The users table definitely looks more interesting. Let’s look at the table schemas to get more information:

We can see that there’s a flag field in the users table. With another query, we can extract all flag values:

All of the N/A values are messing up our results. Let’s filter them out and try again:

The flag is therefore: sun{ju57_4n07h3r_5ql1_ch4ll}

Web: Wrestler Name Generator (150)

We’re given a link to a website which let’s you generate a random wrestler name:

Once we’ve inputted the first and last name, we’re given the following response:

You can quickly notice that the URL now has a large Base64 string appended to it:

Decoding this gives us the following data:

Since we have XML data, let’s try an XXE attack. To form our payload, we must embed a malicious entity into a field with a known response.

As you can see, I’ve embedded /etc/passwd into an entity, and displayed the entity in the firstName field. Let’s Base64+Url encode this, and pass it in as our input in the URL.

It looks like we have LFI! There doesn’t seem to be anything interesting in that file, so I looked around the filesystem. I noticed that some files didn’t show any data, and so I added a Base64 wrapper before the filename so that large/binary files are shown too:

We could then encode this, and resubmit it in order to get a Base64 response. It would be helpful to get the source code for this operation, so I sent the payload back with generate.php selected:

We can then see thus see the source code:

This tells us that by accessing the website from a local address, we can get the flag. Let’s send off another payload to the webserver and retreive the flag:

After encoding this, we get the following response:

The flag is therefore sun{1_l0v3_hulk_7h3_3x73rn4l_3n717y_h064n}.

Scripting: Entry Exam (250)

The website given looks as follows:

Beautiful :’)

We are given this scantron:

We’re also given a webpage with questions on, and the option to upload a complete scantron (http://archive.sunshinectf.org:19005/practice):

This challenge consists of little other than scripting an automatic scranton-filler and uploader, as shown below:

After leaving this to run 10 times, we get given the flag in the response:

Contact me:
Personal Website
Twitter: georgeomnet
Github: Ge0rg3
Discord: George#1234

A collection of write-ups for various systems.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store