Conversation
SessionManagement5SetToken claimed to email a reset token but never generated or stored one; SessionManagement5ChangePassword accepted any base64'd timestamp within the last 10 minutes as valid, so an attacker could forge a token for any user (including admin) purely from their own clock, with no server interaction required. - SessionManagement5SetToken now issues a real SecureRandom token per user and records it server-side with an issue time. - SessionManagement5ChangePassword now requires that exact token (constant-time compared), keeps the 10-minute freshness window, and consumes the token on success or expiry (single use). - SessionManagement5 now verifies the password for every login attempt before trusting the looked-up role, instead of only when the role lookup already resolved to admin. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
🏆 Security Shepherd — CTF Patch Score1 / 40 challenges patched
Commit: 🎉 Your result is on the leaderboard — see where you rank! 🏆 |
Author
|
Closing as part of a full stand-down of this CTF push. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes Challenge-19-Session-Mgmt-5 (A07 - Identification and Authentication Failures).
Vulnerability:
SessionManagement5SetTokenclaimed to email a password-reset token but neveractually generated or stored one server-side, and
SessionManagement5ChangePasswordvalidated thesubmitted
resetPasswordTokenpurely by base64-decoding it into a timestamp and checking that thetimestamp was "recent" (within 10 minutes) - no server-side secret or randomness was ever involved.
Since the token was entirely self-describing (just the current time, base64'd), any attacker could
forge a valid token for any username - including
admin- purely from their own clock, without everreceiving a real reset email, then use it to set that user's password and log in.
SessionManagement5(the login handler) also only verified the submitted password when a prior,password-less username lookup already returned the
adminrole - any other role was granted a signedin "Pleb" session without the password ever being checked. That's not directly key-granting, but it's
the same missing-authentication-order class of bug living in the same file, so it's tightened as part
of the same fix.
Fix:
SessionManagement5SetTokennow generates a real cryptographically random per-user token(
SecureRandom, 32 bytes) and records it server-side (with issue time) the moment a reset isrequested for an existing user - nothing about the token is derivable from the client-visible
timestamp anymore.
SessionManagement5ChangePasswordnow requires the exact previously-issued token for that username (constant-time compared), still enforces the original 10-minute freshness window, and
consumes (single-uses) the token on both success and expiry so it can't be replayed.
SessionManagement5now checks the password on every login attempt before trusting the looked-uprole, instead of only for rows that already resolved to
admin.Local verification (WSL, full docker-compose Tomcat+MariaDB+Mongo stack built from this branch):
mvn -o compileis clean.servlets over real HTTP:
Base64(current timestamp)) foruserName=adminandPOSTing it to
.../ChangePassis now rejected ("Token is invalid")..../SendTokenissues a realserver-side token; submitting that exact token to
.../ChangePasssucceeds, and logging in tothe sub-app with the new password then returns the admin result key.
Files changed:
src/main/java/servlets/module/challenge/SessionManagement5.javasrc/main/java/servlets/module/challenge/SessionManagement5ChangePassword.javasrc/main/java/servlets/module/challenge/SessionManagement5SetToken.java