Challenge writer POV: BSidesSF 2021 CTF (Cloud)

Here is this year’s write-up for my cloud challenges from BsidesSF CTF 2021. This year I wrote two cloud challenges — Whole New Me and Shout into the Void. As always, I tried to make them fun and applicable in the real world. With that let’s dive into the challenge writer PoV for these challenges.

Whole new me

This challenge centered around App Engine, Google’s serverless platform for developing and hosting web applications. Specifically, it focused on how App Engine managed application versioning. I tried to hint towards versioning through the name, domain (appspot.com) and description,

If a player inspected the HTML source, they would quickly spot a helpful comment -

I was hoping this would nudge players towards looking for older versions of the application. Most started by looking for “.git” directories, “.bak” and “.old” file extensions in hopes of finding an older version. Many reached out at this stage to ask if they needed a specific wordlist or if the challenge was broken. I nudged players to explore the infrastructure, given that it was a cloud challenge. This seemed to redirect their attention to App Engine and its documentation around versioning. Google cloud’s documentation outlines how the URL for each version of the Appengine service is structured -

VERSION-dot-SERVICE-dot-PROJECT_ID.REGION_ID.r.appspot.com

Comparing this against the challenge URL — https://bustling-bay-304920.wl.r.appspot.com/, we currently have the PROJECT_ID (bustling-bay-304920) and the REGION_ID (wl).

The SERVICE string is used to route traffic to different backend services, if you don’t specify one it will use the default service. This leaves only the VERSION_ID string, some players searched for details on App Engine versioning and stumbled on resources that revealed the format. Others deployed an App Engine application and noticed the format of the version generated.

The default VERSION_ID string uses the format YYMMDDtHHMMSS, I reduced the bruteforce window significantly by adding the “Last updated” field on the site.

This meant that the players only had to bruteforce the seconds field — 0 to 60. Going back two versions will reveal the version https://20210228t135033-dot-bustling-bay-304920.wl.r.appspot.com/ which has the flag as an HTML comment on the site.

In general, I try to minimize the bruteforcing effort in my challenges as much as possible, if it requires a wordlist I typically add a hint to indicate it. Overall, I was happy that 5 teams figured out the solution and the detailed write-ups have been fun to read.

Shout into the void

This challenge explored what an attacker could do with a leaked GCP Service Account Key. Players were directed to visit a web application on App Engine which claimed to allow users to share their thoughts freely without trace.

I hinted to the presence of a .git directory through robots.txt,

There are a number of tools available to retrieve git repositories including the nmap script http-git and internetwache’s GitDumper. Once the player retrieves the repository, they can run git log/ git show to examine the current state.

The commit message “clean up complete” should indicate that there was a file that was removed. Viewing the previous commit, will reveal that a service account key was checked-in and deleted. Plugging this into gcloud shows that key is still active,

The players needed to figure out what permissions the key had, given that it didn’t have the permission to list permissions the only way to go about this was to try different commands. This would enable them to determine that the key had read access to logs, most notably the App Engine’s request logs.

Looking through the logs, players will notice a repeated message being posted which linked to a *-flag.txt on a GCS bucket. This world-readable file contained the flag — CTF{Aud1t_th3_l0g5}. Unfortunately, some players were spamming messages in the flag format (CTF{}) requiring me to more aggressively spam the link to the flag using a cron job. Overall, this challenge was solved 27 times and received a lot of positive feedback over chat. Some players remarked that the bruteforcing aspect was cumbersome, but I want to reiterate that this is how you would enumerate permissions for Service Account keys in the real world when you cannot list their permissions through IAM. If you are interested in learning more about Service Account Keys, I highly recommend Dylan Ayrey and Allison Donovan’s Defcon talk on Lateral Movement and Privilege Escalation in GCP.

A big shout-out to Mandatory for the brainstorming and challenge writing support.

Security Engineer in silicon valley, foodie, gamer and serial doodler. Specialize in red teaming and application security.

Get the Medium app

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