Category: Web Vulnerability: Mass Assignment / Insecure Parameter Binding Hint Provided: "Improper Authorization has been fixed! I think we are ready for production!"

1.1 Initial Reconnaissance

The challenge presented a user registration and login portal with no immediately obvious attack surface. The key differentiator was the downloadable ZIP file containing the backend source code — app.py. In a real engagement, this is akin to having access to a .git directory or a leaked repository, and it's a massive advantage.

None
None

1.2 Vulnerability Identification (Static Code Analysis)

Focusing on the /api/register endpoint revealed the flaw:

None
Caption: The vulnerable code. record.update(incoming) overwrites the 'role' field if supplied by the attacker.

The developer correctly initialized the record dictionary with a secure default role: 'standard'. However, the subsequent record.update(incoming) merges the entire user-supplied JSON object into the record dictionary. Because dict.update() overwrites existing keys without discrimination, an attacker can supply a "role": "admin" field in the registration request to escalate their privileges.

This is a classic Mass Assignment vulnerability. The application trusts the client to supply only expected fields, but fails to enforce an allow-list of permitted parameters.

1.3 Exploitation Path

  1. Register a new account, injecting the role parameter.
  2. Log in with the newly created admin account.
  3. Access the /admin page, which checks session.get('role') == 'admin'.

1.4 Step-by-Step Exploitation

Step 1: Register an Admin Account Send a POST request to /api/register with a JSON payload that includes the "role": "admin" key-value pair.

None
Caption: Using curl to register an account with the extra 'role' field. The server accepts the payload.

The server responds with a redirect to the login page, confirming account creation.

Step 2: Log In Use the credentials from Step 1 to authenticate via the login form. The session cookie now identifies the user as having the admin role.

None
Caption: Logged in as the newly created admin user. The dashboard appears normal, but we now have elevated privileges.

Step 3: Retrieve the Flag Navigate to /admin. The application verifies the session role and renders the admin dashboard, which contains the flag.

None
Caption: Accessing the /admin endpoint reveals the flag, confirming our privilege escalation.
None

1.5 Key Takeaways

  • Never use dict.update() (or similar object merge functions) directly with untrusted input. Always explicitly extract only the expected fields.
  • Implement a strict allow-list for parameters that can be modified by the user. Libraries like Marshmallow or Pydantic make this straightforward.
  • "Fixing" authorization on the frontend without addressing the backend API is a recipe for disaster.