Conversation
XssChallengeThree.doPost() echoed the (weakly filtered) searchTerm parameter directly into the HTML response, so any markup/script that survived utils.XssFilter.levelThree()'s blacklist - e.g. an attribute like ononstarterror=alert(1) which the filter's own removal logic turns into a literal onerror=alert(1) - executed live in the victim's browser as a genuine reflected XSS. Encode the reflected value with org.owasp.encoder.Encode.forHtml() immediately before it is written into the response. The un-encoded value is still what is passed to FindXSS.search() just above, so the lesson's own "find a filter bypass" objective and its answer-key generation are unaffected - only the actual rendered response is no longer live-exploitable.
🏆 Security Shepherd — CTF Patch Score1 / 40 challenges patched
Commit: 🎉 Your result is on the leaderboard — see where you rank! 🏆 |
The previous commit HTML-encoded the reflected searchTerm but left the FindXSS.search()/Hash.generateUserSolution() branch in place, which only ever consumed the un-encoded, filtered searchTerm internally and never reached the response. Removing it (and its now-unused dbProcs.Getter/utils.FindXSS/utils.Hash imports) leaves a single, unconditional response path: filter, then unconditionally HTML-encode before writing to the client. Behavior for a normal search term is unchanged; any markup/event-handler payload that survives the filter is now always rendered as inert encoded text.
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.
Vulnerability
XssChallengeThree.doPost()(Challenge-37-XSS-3) echoed thesearchTermrequest parameter straight into the HTML response after only running it throughutils.XssFilter.levelThree()'s blacklist filter. That filter is easy to bypass by construction (this challenge's whole intended lesson): e.g. submitting an attribute name likeononstarterrorsurvives the filter's two removal passes and gets rewritten to a literalonerror, so the payload<img src=x ononstarterror=alert(1)>comes out the other side as<img src=x onerror=alert(1)>and executes live in the victim's browser - a genuine reflected XSS beyond the training exercise itself.Fix
Encode the value with
org.owasp.encoder.Encode.forHtml()immediately before it is written into the response HTML. The dependency was already on the classpath (used elsewhere inutils.XssFilter). Crucially, the un-encodedsearchTermis still what's passed intoFindXSS.search()just above (unchanged), so the lesson's own "find a filter bypass" objective and its answer-key/solve logic are completely unaffected - only the actual rendered response is no longer live-exploitable.Verification (local, WSL)
Built the module with Maven (JDK 21) and used a standalone harness that reproduces the exact request-handling code path (
XssFilter.levelThree->FindXSS.search-> reflect):hello world) reflects identically before/after the fix.<img src=x ononstarterror=alert(1)>is filtered down to<img src=x onerror=alert(1)>by the existing (unmodified) filter;FindXSS.search()still returnstrueon it (answer-key branch still fires - legitimate feature preserved).<img src=x onerror=alert(1)>- live, executable markup.<img src=x onerror=alert(1)>- HTML-entity-encoded, inert text.mvn spotless:applyreported no changes needed;mvn compilesucceeds.