Hint: Broken access control. Are there API endpoints that the frontend isn’t using?
When I started this challenge, the first thing I did was fire up Burp Suite. Since we are dealing with a web application, intercepting and analyzing every request after every click is my standard go-to method.
I navigated to the lab environment and immediately created an account to gain access. The application turned out to be a speed-typing practice game, complete with a dashboard and a leaderboard.
Enumeration
After poking around the application for a bit, I switched over to Burp Suite to review the traffic it had captured in the HTTP history tab. Almost immediately, a specific GET request caught my eye: a call to /api/stats. Given the hints provided in the lab description, this seemed like the perfect place to start digging.
Initial Access & Exploitation
To get a better look at how this endpoint worked, I sent the GET /api/stats request over to Burp Repeater. I fired off the request and received a JSON response containing my current typing statistics, including my best_wpm and avg_wpm.
My immediate thought was:
Is it possible to cheat the system and change the Words Per Minute (WPM) to something ridiculous, like 1000?
To test this theory, I took the JSON data from the server’s response, pasted it directly into the body of my request, and changed the HTTP method from GET to PUT. I hit send, hoping to overwrite my stats.
The response I got back was:
{"error":"No valid fields to update"}
I was quite surprised by this. I didn’t get a 403 Forbidden error (which would mean I wasn’t allowed to do this), but the update didn’t work either. It felt like the server just didn’t understand what I was trying to hand it.
The Obstacle and The Breakthrough
I decided to do some research on this specific error behavior. I stumbled upon an article explaining how to parse JSON request bodies in Express.js with body-parser.
Reading through the documentation, the puzzle pieces fell into place. I realized that when sending a PUT or POST request with a JSON body, the Express.js middleware relies on the Content-Type header to know how to parse the incoming data. Because I hadn’t explicitly declared Content-Type: application/json in my request, the server’s body-parser simply ignored my payload, resulting in the “No valid fields to update” error.
Armed with this new knowledge, I went back to Burp Repeater. I manually added the missing header to my PUT request:
Content-Type: application/json
Once I included that and sent the request again, the server successfully parsed my JSON payload and updated my stats. More importantly, the server responded with the flag!
- Burp Suite (Community Edition): Proxy, HTTP History, and Repeater for intercepting and modifying API requests.
- Web Browser: For initial application enumeration and account creation.
Summary
- Key Steps: I discovered an
/api/stats endpoint, attempted to manipulate my typing stats via a PUT request, and debugged a parsing error by correctly applying HTTP headers.
- What I Learned: This challenge was a great reminder of how underlying backend frameworks (like Express.js) handle data. Even if an endpoint is vulnerable to manipulation, the exploit won’t work if you don’t speak the exact protocol language the middleware expects.
- Crucial Mistake/Takeaway: Assuming that just throwing JSON into a request body is enough. The
Content-Type: application/json header is absolutely critical for backend parsers to interpret the payload correctly. Though the lab was relatively straightforward, diving into why the error occurred instead of just guessing led to a valuable learning moment.