NahamCon CTF 2025: “The Mission”
A deep dive into one of the most thrilling web challenges from NahamCon CTF 2025—GraphQL injections, 403 bypasses, heapdump leaks, and more.
Introduction
Hi everyone! I’m Vikram and I’m back with something exciting. This time, my team 0bscuri7y and I participated in NahamCon CTF 2025, and we proudly secured the 13th position among some of the best players out there!
Huge shoutout to my awesome teammates—Bhavya, Shubham, Rishabh, Shivendoo, Vatsal, and Vaibhav for pulling this off.
NahamCon CTF 2025 delivered an incredible web challenge titled “The Mission”, blending classic web exploitation techniques with a compelling narrative.
In this write-up, I walk through my step-by-step approach to solving the challenge. With six cleverly hidden flags, realistic attack surfaces, and plenty of “aha!” moments, this challenge was a masterclass in modern bug bounty tactics. Here’s how I tackled it, one exploit at a time.
Challenge Description
Welcome to the BugBounty platform, you’ve submitted a report for Yahoo but oh no!! So has STÖK and it looks like you’re going to get dupped! Hack into the platform and change STÖK’s report to duplicate first so you can grab the bounty! You can login with the following details: Username: hacker Password: password123
In this challenge, I take on the role of a bug bounty hunter competing for a payout on a simulated platform. The catch? Another well-known researcher, STÖK, has submitted the same vulnerability report. To make sure I walk away with the bounty, I need to dig into the platform, find a way to tamper with the system, and flag STÖK’s report as a duplicate before mine is.
There were 6 Flags in total to complete this challenge. The challenge also provided a wordlist.txt
file.
The Mission Begins
Flag 1: Spoke too soon :)
After spinning up an instance, you’re given a website which looks like this:
The website had sections like Home, Top Hackers, and Login. But just like any CTF, I checked /robots.txt
first and guess what?
Bingo! I got Flag #1 and an interesting looking endpoint. I was like “Eh! that easy?” But maybe I spoke too soon.
Flag 2: When in Doubt, Wordlist It Out
I couldn’t just walk past that /internal-dash
login page without poking it. I visited /internal-dash/
which redirected me to a login page titled “Internal Dashboard”. My inner hacker instincts screamed “Admin Panel!”
I threw everything I had at it: Default creds? Nope. SQLi? Nah. Session tampering? I wish! Remembering the wordlist.txt
file, I loaded it into DirBuster and started brute-forcing directories.
Soon enough, I found /api/v1
—and it threw a stack trace revealing something juicy: openjdk:19-jdk.
After some research, I learned about the /actuator
endpoint in Spring Boot applications, which can expose sensitive internal data. But when I tried to access it, I got a 403 Forbidden.
A WAF? Maybe I was on the right track. I quickly used a 403 bypass plugin in Caido.
Bypassed that 403 with a sneaky character encoding, and yes sir! I was in. I grabbed Flag #2 and stumbled upon another juicy file: /heapdump
.
Flag 3: Made It In… kinda
I downloaded the heapdump and it was like finding a treasure map.
Looking closely at the heapdump, I realized it contained a POST request. I replayed the request and boom, got a valid internal dashboard token in return.
After checking the /logout
endpoint, I noticed a cookie named int-token
was being cleared. So, I took the token from the heapdump and set it as the int-token
cookie in a request to /internal-dash/
.
1
2
3
4
GET /internal-dash/ HTTP/1.1
Host: challenge.nahamcon.com:30510
Cookie: int-token=a1c2860d05f004f9ac6b0626277b1c36e0d30d66bb168f0a56a53ce12f3f0f7a
...
This time, it worked! I was logged into the internal “Bug Bounty Report Lookup” dashboard.
That got me Flag #3. However, the dashboard required a report_id
, which I didn’t have yet.
Flag 4: Peeking Where I Shouldn’t (Thanks, GraphQL)
Back on the main domain, I used the provided credentials (hacker
:password123
) to log in.
Inspecting the network traffic, I found a /api/v2/graphql
endpoint. It looked like it might be vulnerable to GraphQL injection, and spoiler alert: IT WAS.
I sent this classic test payload:
1
{"query": "{ users { id username email } }"}
To my surprise, the server responded without any authentication checks, returning a full list of registered users.
Got Flag #4! Out of all the users, one stood out: Stok. I grabbed his user ID and used the /api/v2/reports
endpoint to get all his submitted reports.
Now I had two crucial things:
- Stok’s ID:
15ee453d-18c7–419b-a3a6-ef8f2cc1271f
- Stok’s Report ID:
c03dd42e-d929–4a50–9a8e-1ab6b2dd5e8a
Let’s jump back to the internal dashboard.
Flag 5: Wait, there’s more??
Back on the internal dashboard, I entered Stok’s report ID but was hit with a 403 Forbidden. Even with a valid token, I wasn’t authorized to view that report. Digging into the dashboard’s source code, I noticed a change_hash
parameter was required to update a report’s status, which I couldn’t get due to the 403.
After some experimentation with the id
parameter, passing id
as x/../../../search?q=<REPORT_ID>
tricked the server into leaking the change_hash
.
With the hash, I was able to modify the report’s status. I quickly marked Stok’s report as “Duplicate”…
…and updated mine to “Accepted”.
After logging back into the main dashboard, there it was: Flag #5. A clean finish to a sneaky privilege escalation chain.
Flag 6: Am I Adam Langley?
Just when I thought I was done, there was one last bonus flag. I noticed a “Bug Bounty Assistant” bot on the dashboard. What if I pretended to be someone else? I spoofed my name to Adam Langley and tricked the bot.
Boom! It spilled the final secret, and Flag #6 was secured.
Closing Thoughts & Shoutouts
Big thanks to Adam Langley for crafting such a fun, challenging, and beautifully designed CTF. And a shout-out to John Hammond and Ben Sadeghipour for organizing NahamCon 2025 and pulling it all off so smoothly.
Happy hacking and see you next time with more cool stuff! 🚀