From aa086e6740101c1f410cc73b7dad76edf4b3bb8a Mon Sep 17 00:00:00 2001 From: beanbeah <24713371+beanbeah@users.noreply.github.com> Date: Sun, 9 Aug 2026 11:20:08 -0700 Subject: [PATCH 1/3] Fix VERB-based access control bypass in Challenge 8 voting endpoint Assignment8.vote() denylisted only the literal string "GET" via request.getMethod().equals("GET") and let every other HTTP verb fall through to the privileged branch that records a vote and returns the flag in an X-FlagController response header. Since the WebGoat UI only ever calls this endpoint with GET (challenge8.js issues $.get(...)), any other verb - POST, PUT, HEAD, etc. - reached the "authenticated" branch despite there being no actual authentication check at all, letting an attacker who simply changes the request method obtain the flag. Replace the denylist with a fail-closed default: since there is no real login/session check backing this endpoint, no verb should reach the privileged branch, so every request (regardless of method) now gets the same not-logged-in response that GET already returned. The legitimate feature is unaffected because the only real caller (challenge8.js) always issues GET requests, which behave identically to before. Closes Challenge-81-JWT-Voting-Challenge (A01 Broken Access Control). Co-Authored-By: Claude Sonnet 5 --- .../challenges/challenge8/Assignment8.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/owasp/webgoat/lessons/challenges/challenge8/Assignment8.java b/src/main/java/org/owasp/webgoat/lessons/challenges/challenge8/Assignment8.java index ff74256e1..b0ec1bda5 100644 --- a/src/main/java/org/owasp/webgoat/lessons/challenges/challenge8/Assignment8.java +++ b/src/main/java/org/owasp/webgoat/lessons/challenges/challenge8/Assignment8.java @@ -41,18 +41,20 @@ public class Assignment8 implements AssignmentEndpoint { @ResponseBody public ResponseEntity vote( @PathVariable(value = "stars") int nrOfStars, HttpServletRequest request) { - // Simple implementation of VERB Based Authentication - String msg = ""; - if (request.getMethod().equals("GET")) { - var json = - Map.of("error", true, "message", "Sorry but you need to login first in order to vote"); - return ResponseEntity.status(200).body(json); - } - Integer allVotesForStar = votes.getOrDefault(nrOfStars, 0); - votes.put(nrOfStars, allVotesForStar + 1); - return ResponseEntity.ok() - .header("X-FlagController", "Thanks for voting, your flag is: " + flags.getFlag(8)) - .build(); + // Previously this endpoint tried to gate access by comparing request.getMethod() against the + // literal string "GET" and letting anything else fall through to the authenticated-only vote + // logic below. That is a denylist built on attacker-controlled input: a servlet container + // will happily hand a @GetMapping handler a request whose method is HEAD (or another verb + // that was never explicitly rejected) while request.getMethod() still reports that original + // verb, so simply not saying "GET" was enough to slip past the check and reach the branch + // that awarded the vote and leaked the flag in a response header - headers survive even on a + // HEAD response. Since this handler has no real authentication/session check behind it at + // all, there is no verb that should be allowed to reach the privileged branch, so it is + // removed entirely and every request - whatever method it arrives on - gets the same + // "not logged in" response. + var json = + Map.of("error", true, "message", "Sorry but you need to login first in order to vote"); + return ResponseEntity.status(200).body(json); } @GetMapping("/challenge/8/votes/") From 4ad4734b901b18770d44898dadcb4830083aafe7 Mon Sep 17 00:00:00 2001 From: beanbeah <24713371+beanbeah@users.noreply.github.com> Date: Sun, 9 Aug 2026 11:41:55 -0700 Subject: [PATCH 2/3] ci: bump lombok to 1.18.46 to unblock JDK 25 scoring build The CI scorer image (eclipse-temurin:25-jdk-noble) fails to compile with lombok 1.18.36 pinned in pom.xml: 'Fatal error compiling: java.lang.ExceptionInInitializerError: com.sun.tools.javac.code.TypeTag :: UNKNOWN'. Lombok 1.18.36 predates JDK 25 compiler-internals support; 1.18.46 fixes it. Build-tooling-only change, no runtime/functional code touched. Co-Authored-By: Claude Sonnet 5 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b5ad9015d..3259ca38a 100644 --- a/pom.xml +++ b/pom.xml @@ -238,7 +238,7 @@ org.projectlombok lombok - 1.18.36 + 1.18.46 provided true From 211c6bd03fe19411fa21b3fed24f4465453e1ef2 Mon Sep 17 00:00:00 2001 From: beanbeah <24713371+beanbeah@users.noreply.github.com> Date: Sun, 9 Aug 2026 11:47:06 -0700 Subject: [PATCH 3/3] chore: retrigger CI scoring (previous run's leaderboard POST returned 500) Co-Authored-By: Claude Sonnet 5