Skip to content

Fix: IDOR allows editing another user's profile via PUT /IDOR/profile/{userId} - #490

Closed
beanbeah wants to merge 2 commits into
OWASP-CTF:dc34-ctffrom
beanbeah:ctf/r2-challenge-challenge-45-idor-edit-other-profile
Closed

beanbeah wants to merge 2 commits into
OWASP-CTF:dc34-ctffrom
beanbeah:ctf/r2-challenge-challenge-45-idor-edit-other-profile

Conversation

@beanbeah

@beanbeah beanbeah commented Aug 9, 2026

Copy link
Copy Markdown

Vulnerability

IDOREditOtherProfile.completed() (PUT /IDOR/profile/{userId}) trusted the client-supplied path variable and/or the JSON body's userId field to decide which user's profile record to write, without any check tying the request to the session's actual authenticated user. Any authenticated user could submit a different user's id and modify that user's color/role fields.

Fix

The endpoint now requires that both the path variable and (if present) the body's userId match the session's authenticated user id (idor-authenticated-user-id) before any write occurs. Any mismatch is rejected regardless of the role/color values supplied. The role field is no longer settable by the client at all, closing a privilege-escalation side channel through the same endpoint. Editing your own profile still works.

Local verification (WSL)

Built and booted the app locally (JDK 25, matches CI). Registered a user, logged into the IDOR lesson as tom/cat (authenticated id 2342384).

  • Exploit (now fails): PUT /IDOR/profile/2342388 (Buffalo Bill's id) with {"userId":"2342388","color":"red","role":1} -> lessonCompleted:false. Also tried the path/body-mismatch variant (own id in path, other user's id in body) -> also false.
  • Legitimate feature (still works): PUT /IDOR/profile/2342384 (own id) with {"userId":"2342384","color":"blue"} -> lessonCompleted:true, profile updated. Same with no userId in the body, and with an attempted role override (role stays unchanged, confirming no escalation is possible).

🤖 Generated with Claude Code

beanbeah and others added 2 commits August 9, 2026 08:37
Every branch built against this base was failing to build/boot in CI
with ExceptionInInitializerError: TypeTag :: UNKNOWN, because lombok
1.18.36 can't reflectively patch JDK 25's javac internals. Baking the
fix into the fork's own dc34-ctf base so every future branch inherits
it automatically instead of needing a manual per-branch cherry-pick.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
IDOREditOtherProfile.completed() trusted the client-supplied path
variable and request body to decide whose profile record got written,
only checking role/color values after the fact. This let any
authenticated user submit another user's userId (via the path or the
JSON body) and modify that other user's profile (color/role) without
any server-side authorization check tying the request to the
session's actual authenticated identity.

Now the endpoint requires that both the path variable and, if
present, the body's userId match the session's authenticated user id
before any write happens; any mismatch is rejected outright regardless
of what role/color values were supplied. Editing your own profile
(the legitimate action) still succeeds, and the role field can no
longer be set by the client at all, closing off a privilege-escalation
side channel through the same endpoint.
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

🏆 WebGoat — CTF Patch Score

░░░░░░░░░░░░░░░░░░░░  3 / 137 pts  (2%)

1 / 69 challenges patched

Per-challenge detail is withheld — it would reveal the rubric.

Commit: fac7e33 · scoring run

🎉 Your result is on the leaderboard — see where you rank! 🏆

@beanbeah

beanbeah commented Aug 9, 2026

Copy link
Copy Markdown
Author

Closing as part of a full stand-down of this CTF push.

@beanbeah beanbeah closed this Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant