> ## Documentation Index
> Fetch the complete documentation index at: https://docs.jaspervanzeir.be/llms.txt
> Use this file to discover all available pages before exploring further.

# Sokudo

<Tip>
  Hint: Broken access control. Are there API endpoints that the frontend isn't using?
</Tip>

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.

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/sokudo-01-stats-api-request.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=60edf2b620f95eb04a1bb2b50f55e486" alt="Stats API request" width="1520" height="903" data-path="images/sokudo-01-stats-api-request.avif" />
</Frame>

## 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?\_ *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:

```json theme={null}
{"error":"No valid fields to update"}
```

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/sokudo-02-no-valid-fields-error.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=e0fd75a97d14667e2760175dd6d50954" alt="No valid fields error" width="1520" height="904" data-path="images/sokudo-02-no-valid-fields-error.avif" />
</Frame>

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](https://json-parser.json-format.com/blog/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:

```shellscript theme={null}
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!

<Frame>
  <img src="https://mintcdn.com/z3r0d4yj/Lqj5mHPBxYtIomZK/images/sokudo-03-content-type-json-flag.avif?fit=max&auto=format&n=Lqj5mHPBxYtIomZK&q=85&s=f9960be0e78d01655608a5215d3d3a08" alt="Content-Type JSON flag" width="1520" height="906" data-path="images/sokudo-03-content-type-json-flag.avif" />
</Frame>

***

## Tools Used

* 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.
