This challenge presented a seemingly simple blog application with a login form. The goal was to find and access a hidden admin panel to retrieve the flag. No source code was provided — just a URL and a hint: "Not everything is linked."
I started by browsing the application normally. The site had a homepage, a few blog posts, and a standard login form. Viewing the page source revealed nothing unusual — no hidden comments, no JavaScript clues. The login form posted to /api/auth and returned generic error messages, ruling out easy SQL injection. Time to look deeper.
The hint about unlisted pages pointed toward forced browsing. I used gobuster with a common wordlist: gobuster dir -u http://target -w common.txt. Within seconds, it revealed /admin, /backup, and /debug. The /adminpath returned a 403 Forbidden, /backup returned a 404, but /debug returned a 200 with an interesting JSON response containing environment variables — including aSESSION_SECRET.
Examining the cookies, I found a session cookie that looked like a signed JWT. Decoding it on jwt.io revealed a payload with {"role": "user", "id": 1}. Since I now had theSESSION_SECRET from the debug endpoint, I could forge a new token. I changedrole to admin, re-signed the JWT with the leaked secret, and replaced my browser cookie.
Refreshing /admin with the forged cookie bypassed the 403 and loaded the admin dashboard. The flag was displayed at the top of the page: FLAG{h1dd3n_4dm1n_p4n3l}. The entire chain — from recon to flag — took about 12 minutes.
This challenge reinforced several important lessons: never expose debug endpoints in production, always keep secrets out of environment dumps, implement proper role-based access control that doesn't rely solely on client-side tokens, and remember that security through obscurity (hiding the admin path) is not a real defense. Every endpoint must enforce authorization independently.