Defcon 30 Recon Village CTF Write-up
The write-up for challenges in the Recon Village CTF from Defcon 30.
Last week at Defcon 30, some friends and I attempted the Recon Village CTF. While spending most of Friday grinding out a CTF in a hotel room wasn't my original plan, it turned out to be a lot of fun.
After a rather late night, we ended up solving most of the challenges and got first place in the competition. This is the write-up for the CTF's challenges.
CTF Challenges
Jerlean's 54th Birthday
Jerlean was in Vegas for their 54th birthday recently. Which hotel did they stay at?
Our natural instinct was to start Googling for someone named Jerlean, but Google didn't return anything relevant. We then tried to find Jerlean on Facebook, but that didn't bear fruit either. Turns out Instagram was the key.
By querying "vegas birthday" on Instagram and scrolling down, you'll eventually bump into the following picture:
It's an ad with no textual references to Jerlean, but you can glean all of the data from the photo. If you notice the post's location, you'll see that this was posted in New York-New York.
Spammy Email Domain
On 11 August, what was the primary email domain from which spam was reported as coming from 185.129.62.62 and 107.189.28.253 (two bot IPs)?
To figure out the domains associated with the IP addresses, we looked up the addresses in a forum spam database. The first IP address had a fair bit of activity on August 11.
If you look at the emails sent on that date, you'll notice that the most common domain seems to be hiroyuki4010.yoshito33.inwebmail.fun
.
Wedding in Costa Rica
Wanting to remain anonymous online, discreetly named 'Phonenumber' from Costa Rica has a friend who works for Facebook. When did his friend get married?
Since we were searching for a person and his friends, we turned to Facebook. By querying for people named Phonenumber
, you'll find an account that's based in Costa Rica.
Next, we look through this person's friends list to see if there are any friends who work at Facebook. There happen to be two people. One of them isn't in a relationship, but the other person is married. If you check out this person's "about" page, you'll see the date when he got married.
Missing Person Report
You're investigating a missing person who went missing following a party in 2019. While working through case notes you've come across the following NTIyMyBTb3V0aCBCcmFlc3dvb2QgQm91bGV2YXJkLCBIb3VzdG9u What date was the pool party?
The payload NTIyMyBTb3V0aCBCcmFlc3dvb2QgQm91bGV2YXJkLCBIb3VzdG9u
attached to the CTF question is base64 encoded. If you decode it, you end up with an address in Houston, Texas. Googling the address combined with "party" and "2019" will yield a single search result in the form of a Pastebin: https://pastebin.com/BNwRBAX4
The paste contains an email detailing plans for a pool party that will happen "this Saturday." The email was sent on April 18, 2019, so you can infer that the pool party itself was held on April 20, 2019.
Party Co-host
This is a follow-up to the previous question.
There are two hosts of the party, one is Vanessa. What is the last name of the other host?
If you re-read the email from the Pastebin, you'll notice a few bits of information:
- The party was held in Houston, Texas.
- The email addresses and names of the recipients are public.
- The hosts are named Vanessa and Meghana.
Searching for the hosts directly on Facebook doesn't yield too many results. However, by looking up some of the email recipients (especially those with uncommon names), you'll eventually find people based in Texas. Looking through their friends list will allow you to find Vanessa. Looking through Vanessa's friends list will allow you to find Meghana.
As a reminder, these are real people. Please respect their privacy.
Maiden Name
Callum lives in Scarborough, Toronto and works with kids. What's his wife's maiden name?
Googling up Callum with his location and profession will lead to his LinkedIn page and reveal his last name. Looking up his full name and location on Facebook will lead to his Facebook page, which also contains the profile of his wife.
However, his wife changed her last name, and her maiden name isn't in her profile. But those who are observant will notice that the Facebook URL does not update unless manually changed. Callum's wife's URL contains her maiden name.
Password Breach
This is a follow-up to the previous question.
Callum's password has been breached in connection with his primary email. What is it?
Despite finding Callum's social media profiles, we weren't able to find his email address. As a result, we enumerated potential emails. (Using Gmail to autocomplete was helpful in filtering out potential and valid emails.) It turns out that his email used the common [email protected]
format.
Then, Googling the email address along with terms like "password" led to a Pastebin that contained a password dump for emails. Callum's password was included in the paste: https://pastebin.com/1LeMmy4X
Open Source
The next few challenges are all based on CryptoRama, a fictional company.
Hi, I'm Eva Hesington. Remember me from last year? I am the founder of CryptoRama. Thanks to your support we have been able to scale the business a lot. I cannot thank the open source community enough. Using Open source tools and platforms, our business has grown and our tech department is now running strong. We could not have done it without these Open Source tools and community. You can visit our website to find out more.
This one had us stumped for a while, as Cryptorama was an actual company. We went down a few rabbit holes to no avail before querying Cryptorama with Eva Hesington's name included. That led to a single search result to a different Cryptorama: https://cryptorama.cloud/
If you checked the source of the website, you'd find the flag. It's embedded in a comment within main.min.js
.
Secret Sharing
We at CryptoRama are very concerned about sharing sensitive information with the outside world and even on the inside. We use secret sharing services. But looks like someone has been manipulating our secrets application and hindering our progress. Can you please check?
The challenge mentions a secret sharing service but does not share any more details. So we need to find what service it's referring to. By looking at the certificate transparency logs for the CryptoRama website, we that there are a few valid subdomains. One of them is https://secrets.cryptorama.cloud/.
When examining the website, we see that it's running SnapPass, a secret-sharing app maintained by Pinterest. Users can write a secret to the app, and the app will generate a URL to view the secret. After the secret is viewed once, it will disappear forever.
There don't seem to be any CVEs associated with SnapPass, so perhaps the site is running a patched version with broken crypto. When looking among the forks of the repo, we see that there's a fork that's created by CryptoRama. And it also has a patch that changes the URL generation. Here's a summary of the patch:
- The encryption key is now the base64 encoded version of a hardcoded secret
6ardCD6XQ49FLrxY6fd7pB3DeeNmzn8Y
. With the base64 encoding, the string will beNmFyZENENlhRNDlGTHJ4WTZmZDdwQjNEZWVObXpuOFk=
. - The secret URL has a prefix of
RV
(from the Redis prefix). - The secret URL additionally takes in the current timestamp.
Overall, the format of the secret URL looks like this:
Although we have an algorithm to generate the secret URLs, it still takes two parameters: a UUID and the timestamp. For both, it's unfeasible to guess or brute force. Therefore, we need another way to make use of the URLs. Our next step is to find a source for the UUIDs and timestamps.
Looking around CryptoRama's Github profile, we find that it has a second repository called Progress Tracker. Every minute or so, the repo updates with a new commit that changes a hash in README.md
.
Notice that the hash in the file is the same format as a UUID. Also notice that every commit has an associated timestamp. If we take those two pieces of data, we have enough information to generate a URL in the SnapPass instance. From trial and error, it seems like the URL expects the timestamp to be of minute precision. If we plug in the converted timestamp and the hash, we get a valid URL.
Every commit in the repository creates a secret that contains the flag. Since it's a one-time use URL, that's why the repository keeps adding new secrets every minute.
Public Server Backup
We lost access to one of our servers. Thankfully we had backups. All you have to do is find a piece (backup) of our server and make it whole by attaching it to another server. If you do this, you will have attained nirvana! Start looking at our website again.
Going back to the Cryptorama website, we notice the picture of Eva. It has a very interesting URL:
Searching for her name on Gitlab yields an account with a single repository containing her personal website. However, more interesting is a file called account.txt
that contains details of her AWS account ID and mentions an EC2 instance.
Since we've learned that she has an EC2 machine and we know her AWS account ID, the next step would be to see if there's any way to find details of her EC2 instance.
AWS allows you to snapshot EC2 instances onto EBS, and it's possible to have those snapshots be public. Since we know the account ID, we have the ability to find all of the public snapshots for the account. To do so, we enumerate through the AWS regions and use the command line to print out public EBS snapshots:
Most of the regions yield nothing, but in us-west-1
, there's a single public snapshot:
We want to inspect the contents of the snapshot. In order to do so, we need to copy the snapshot over to our own account and then create our own EC2 instance that's based on the snapshot.
Once the image is in your account, you can create an EC2 instance, SSH into the machine, and view the flag.
Asset Management
Our junior developer Henry Lopez cannot find his assets. Can you help him please? His credentials are given below: Username: henry.lopez Password: sHTA$H@&sBjPG5
It seems like Cryptorama has an assets server. When we looked at the certificate transparency logs, we saw that https://assets.cryptorama.cloud/ was a valid subdomain. Logging in with Henry's credentials leads us to the asset management page.
From poking around the app, we learn that there's very little data to be found. We also see that the site is running v5.4.3 of Snipe-IT. If you search for CVEs that are present in the running version of the app, you'll find CVE-2022-1511. It's an access control bug that was fixed in the following patch of Snipe-IT.
Because of the bug, users without proper permissions can access restricted resources. The resources don't show up as links in the app's sidebar, but they can just go to the URL directly. The proof of concept shows a normal user visiting the /hardware/requested
endpoint, even though there are no permissions. By doing the same and visiting https://assets.cryptorama.cloud/hardware/requested, we can find the flag.
Control Panel RCE
Now that Henry has his assets, time to try out an application he created. https://control-panel.cryptorama.cloud/
If you visit the website, you'll find a pretty unassuming app. It contains two buttons, one that shows the current working directory, and one that prints the current timestamp.
If you inspect the network requests that happen from clicking the buttons, you'll notice that there's a request to /cmd
that with form data. The payload has a single key, filename
, and the value is either first
or second
depending on which button you clicked.
We then try to break the form by sending a request without the filename
key. It causes the request to fail, because of a BadRequestKeyError
. From looking at the ensuing HTML, we learn that...
- It's running a development build of Flask (since there's a stack trace).
- The
/cmd
endpoint requires a value forfilename
.
Scrolling down the stack trace, you'll find a snippet of the actual application code.
From reading the code, it seems to be...
- Reading the value at
filename
. - Constructing a URL based on that value.
- Sending an HTTP request to get the contents of that URL.
- Running the contents of the HTTP request via
eval
. - Sending the return value of the
eval
as part of the HTTP response.
Though the snippet only covers the logic for local files, we suspected that there must be similar logic for remote files. We have no control of the local file content, but if we hosted our own files and had the server download those, we could in theory do arbitrary code execution.
The fastest way I think of to host files on the public Internet was to run a simple HTTP server and expose it via ngrok
. So I created a directory with some test files and spun up an ngrok tunnel.
Then if you include the entire URL of your remote file as the value in the filename
key, the server will execute the arbitrary code that you wrote. Listing the contents of the directory showed that there was a file called flag.txt
. Then you could command the server to print out the contents of the flag.
Doug's Golfing Experience
Can you locate this field on the outskirts of London in the image attached below. Once you do, what date did Doug leave a review for this place?
This picture seems to have been taken from a plane. The field is also quite distinct, which makes it easy to confirm whether you've found the correct location.
If you've ever flown in a plane before, you'll notice that the picture was taken at a relatively low altitude. A low altitude means that the plane is either landing or departing, which also implies that the plane is close to the airport. The field itself appears to be a golf course. If you search for golf courses near London airports on Google Maps, you'll eventually find a place called Hounslow Golf Park next to Heathrow Airport.
Taking a look at the golf park's website confirms that it's the same field from the photo. Scrolling through the reviews, you'll find a review from Doug that was posted on July 16th.
Meet the Team
Behind every CTF, there are names and faces that made it all a reality. Thanks to the organizers at Recon Village for creating the challenges in this CTF. It's also important to remember that solving this CTF was a team effort. Here are your alligator hunters:
- Chris Rodriguez
- Christian Johnson
- Jeremy Krach
- Andrew Liu (me)
Hope you enjoyed reading this write-up! If you have any questions or feedback, feel free to reach out and share your thoughts.