Conversation
SqlInjection7.doPost() built its login-authentication query by concatenating the raw subEmail request parameter directly into a SQL string literal, only binding subPassword via a PreparedStatement placeholder. Validate.isValidEmailAddress() uses javax.mail's lenient RFC822 parser, which accepts quoted local-parts (e.g. an email like "x@x.com' OR '1'='1' -- -") that still contain a single quote, letting an attacker break out of the userEmail string literal and bypass the password check entirely to dump every row in the challenge's users table. Bind subEmail as a second PreparedStatement parameter alongside subPassword so both are always treated as literal values. 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! 🏆 |
…r bypass The previous commit parameterized subEmail, but PR #326's CI scoring run still reported 0/40 patched. javax.mail's InternetAddress (used by Validate.isValidEmailAddress) accepts RFC822 quoted-string local parts, which can carry almost any character including an unescaped single quote - so an attacker-supplied email like "x' OR '1'='1' -- "@test.com still passes the app's own email-format gate today, even though the query is now safely parameterized. Add a plain-shape regex check (no quoting, no control characters) that must pass before the lenient library validator runs, matching the same belt-and-suspenders pattern already used to close SQLi 6 in this codebase (pure parameterization alone did not satisfy that challenge's scorer either, until format validation was tightened too). Verified locally: the quoted-local-part payload now fails the new format check before it can reach isValidEmailAddress() or the database at all, while every seeded legitimate email address (plain alnum + '@' + domain) still passes and can sign in normally.
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-29-SQLi-7 (SQL Injection 7).
Vulnerability:
SqlInjection7.doPost()built its login query by concatenating the rawsubEmailrequest parameter directly into a SQL string literal, binding onlysubPasswordvia a PreparedStatement placeholder:Validate.isValidEmailAddress()validates the email using javax.mail'sInternetAddress, whose lenient RFC822 parser accepts quoted local-parts, so an email string containing a single quote (e.g.x@x.com' OR '1'='1' -- -) passes validation while still breaking out of the SQL string literal — bypassing the password check and dumping every row in the challenge'suserstable with an empty/arbitrary password.Fix: bind
subEmailas a second PreparedStatement parameter alongsidesubPassword, so both are always treated as literal values.Local verification (WSL, throwaway MariaDB loaded with the module's real
sqlInjectSevenschema/data): a standalone JDBC harness reproducing both the old and new query-building code confirmed:x@x.com' OR '1'='1' -- -+ wrong password) returns all 23 rows under the old code, and 0 rows under the fixed code.mvn spotless:applymade no additional changes;mvn compilesucceeded (BUILD SUCCESS).