Repository navigation
fix: close JDBC resources in SQL injection challenges and lesson (part of #857) - #998
ismisepaul wants to merge 2 commits into
Conversation
…t of #857) Each challenge schema has its own connection pool of three connections. These servlets only closed their connection when the query succeeded, or never closed it at all (SqlInjectionEscaping, SqlInjectionLesson), so a few malformed injection attempts took the level offline until Tomcat was restarted. Open the Connection, Statement and ResultSet in try-with-resources. Only resource handling changes: the queries, filtering, error messages and the order in which exceptions reach each catch block are the same as before. SqlInjectionPoolLeakIT sends five malformed submissions to each level, then a well-formed one that must still reach the database. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
| ResultSet coupons = prepstmt.executeQuery()) { | ||
| try { | ||
| if (coupons.next()) { | ||
| htmlOutput = new String("Valid Coupon for "); |
There was a problem hiding this comment.
This line is unchanged on dev. This PR only re-indents it inside the new try-with-resources block, and these files are training content where the PR changes resource handling only. Tracked for a separate clean-up in #999.
| ResultSet coupons = prepstmt.executeQuery()) { | ||
| try { | ||
| if (coupons.next()) { | ||
| htmlOutput = new String("Valid Coupon for "); |
There was a problem hiding this comment.
This line is unchanged on dev. This PR only re-indents it inside the new try-with-resources block, and these files are training content where the PR changes resource handling only. Tracked for a separate clean-up in #999.
There was a problem hiding this comment.
🟢 Approval recommended
The isolated resource-management changes preserve challenge behavior and include targeted regression coverage, with no unresolved blocking issues.
No open issues 🎉
What changed in this PR
Addresses part of #857 by closing JDBC resources in seven SQL injection challenges and one lesson, preventing challenge-pool exhaustion while preserving intentional vulnerabilities.
Changes:
- Uses try-with-resources for connections, statements, and result sets.
- Preserves existing queries, filtering, and query-error handling.
- Adds integration tests covering repeated malformed requests and subsequent valid queries across all eight servlets.
| File | Description |
|---|---|
src/main/java/servlets/module/lesson/SqlInjectionLesson.java |
Closes JDBC resources after successful and failed searches. |
src/main/java/servlets/module/challenge/SqlInjectionStoredProcedure.java |
Ensures cleanup around stored-procedure queries. |
src/main/java/servlets/module/challenge/SqlInjectionEscaping.java |
Returns connections and closes query resources. |
src/main/java/servlets/module/challenge/SqlInjectionEmail.java |
Ensures cleanup after email searches fail. |
src/main/java/servlets/module/challenge/SqlInjection7.java |
Adds statement and result-set cleanup; retains connection cleanup. |
src/main/java/servlets/module/challenge/SqlInjection6.java |
Closes resources while preserving nested error handling. |
src/main/java/servlets/module/challenge/SqlInjection5VipCheck.java |
Ensures cleanup after VIP coupon queries. |
src/main/java/servlets/module/challenge/SqlInjection5CouponCheck.java |
Ensures cleanup after standard coupon queries. |
src/it/java/servlets/module/challenge/SqlInjectionPoolLeakIT.java |
Adds pool-exhaustion regression coverage for all eight servlets. |
Review effort: Balanced
Review follow-up: fail with a clear message instead of an array index error when the name/value list has an odd length. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The automated tests prove these levels no longer exhaust their connection pools. They don't prove each level can still be solved the intended way, and these are deliberately vulnerable training levels.
Please run this branch, follow the steps, and comment on this PR with the result: pass, or the step that failed and what you saw.
Branch:
dev#857-sqliSet up. Use a machine where the Shepherd Docker volumes can be thrown away:
down -vdeletes their data. JDK 17 and Maven 3.9.2+ are needed.git fetch origin git checkout 'dev#857-sqli' mvn -Pdocker clean install -DskipTests docker compose down -v docker compose up -d --buildadmin/passwordand set a new password when asked.Test
'five times in a row, then a normal input (e.g.test). Each broken input should get the level's usual error message, and the normal input should get a normal answer straight away.It's broken if: a level's cheat-sheet solution no longer returns the result key; or a level answers An Error Occurred! You must be getting funky!, hangs for about 5 seconds, or mentions Connection is not available after the repeated inputs, and keeps doing so until Tomcat restarts.
Part of #857. It doesn't touch the files in #932 (SqlInjection1, 3, 4, 5) or #919 (DirectObject).
What
Each challenge schema has its own connection pool of three connections (#816). These servlets gave their connection back only when the query succeeded.
SqlInjectionEscapingandSqlInjectionLessonnever gave it back at all, so the lesson stopped working after three searches of any kind. A few malformed injection attempts took a level offline until Tomcat restarted, which is the #931 symptom.The
Connection,StatementandResultSetare now opened in try-with-resources in:SqlInjection5CouponCheck,SqlInjection5VipCheck,SqlInjection6,SqlInjection7SqlInjectionEmail,SqlInjectionEscaping,SqlInjectionStoredProcedurelesson/SqlInjectionLessonSqlInjection7already closed its connection on every path, so there only the statement and result set change.The levels are exactly as vulnerable as before
Only resource handling changed. These are all unchanged:
executeQuerystays where it was relative to each inner try/catch, so a failed query still produces the same output. Review withgit diff -w origin/dev: without whitespace, each file only losesConnection conn = …/conn.close()and gains atry (…)header and closing braces.Tests
SqlInjectionPoolLeakIT: for each level it sends 5 malformed inputs, more than the pool's 3 connections, and checks that each one gets the level's error. Then it sends a well-formed input that must still reach the database. The lesson test also runs 5 well-formed searches.On
devit fails 7 of 8 with the pool exhausted, for example:With this change, all 8 pass. Every step of
test.ymlalso passed locally (lint, build, PGP check, compose build, Tomcat config check, unit tests, integration tests).Found on dev, not fixed here
SqlInjection5CouponCheck's catch block uses a missing i18n key: #990. The new IT tolerates it.🤖 Generated with Claude Code