Skip to content

fix: close JDBC resources in Session Management 2, 3 and 5 challenges (part of #857) - #1004

Open
ismisepaul wants to merge 1 commit into
devfrom
dev#857-session-management-2-3-5
Open

ismisepaul wants to merge 1 commit into
devfrom
dev#857-session-management-2-3-5

Conversation

@ismisepaul

@ismisepaul ismisepaul commented Oct 25, 2026 •

Copy link
Copy Markdown
Member

⚠️ Manual testing required before merging

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-session-management-2-3-5

Set up. Use a machine where the Shepherd Docker volumes can be thrown away: down -v deletes their data. JDK 17 and Maven 3.9.2+ are needed.

git fetch origin
git checkout 'dev#857-session-management-2-3-5'
mvn -Pdocker clean install -DskipTests
docker compose down -v
docker compose up -d --build
  1. Open https://localhost, accept the self-signed certificate warning, log in as admin / password and set a new password when asked.
  2. On the Get Started page, tick Enable Unsafe Levels and click Open All Levels.
  3. Admin → Module Management → Change Module Layout → Open Floor, then reload the page, so every level is listed on the left.
  4. Admin → Configuration → Cheat Sheet Management → Enable Cheat Sheets for Administrators. With a level open, the Cheat button in the left-hand menu then shows its solution.

Test

  1. Solve Session Management Challenge 2, 3 and 5 with the solutions from their Cheat buttons and check you get the result keys.
  2. In each of the three, use the level's password reset / change-password form five times in a row with any input. Every attempt should get the level's normal reply, never the funky error.

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. Follows #998 (SQL injection), and touches none of the same files.

What

SessionManagement3ChangePassword and SessionManagement5ChangePassword never closed their connection. Each challenge has a pool of three (#816), so the 4th password change hung and then failed until Tomcat restarted. The other five servlets closed their connection only when no exception was thrown.

Every Connection, PreparedStatement and ResultSet in these servlets is now in try-with-resources:

  • SessionManagement2, SessionManagement2ChangePassword
  • SessionManagement3, SessionManagement3ChangePassword
  • SessionManagement5, SessionManagement5ChangePassword, SessionManagement5SetToken

The levels are exactly as vulnerable as before

Only resource handling changed. The servlets reused one callstmt / resultSet variable for several statements, and try-with-resources variables can't be reassigned. So each statement now gets its own resource (commitStmt, authStmt, addressStmt / addressResult). The SQL, the parameters, the COMMIT order, the messages and the catch each exception reaches are all unchanged. Review with git diff -w origin/dev.

Tests

SessionManagement2To5PoolLeakIT calls each servlet 5 times, more than the pool's 3 connections, and checks that every response came from the database. On dev it fails 3 of 7 with the pool exhausted ("An Error Occurred! You must be getting funky!" from the 4th request). With this change, all 7 pass.

Every step of test.yml passed locally (lint, build, PGP check, compose build, Tomcat config check, unit tests, integration tests).

🤖 Generated with Claude Code

… (part of #857)

Each challenge schema has its own connection pool of three connections.
SessionManagement3ChangePassword and SessionManagement5ChangePassword
never closed their connection, so the fourth password change waited for
the pool timeout and failed until Tomcat was restarted. The other
servlets closed theirs only when no exception was thrown.

Open every Connection, PreparedStatement and ResultSet in
try-with-resources. Statements that were reassigned to one variable now
each get their own resource (commitStmt, authStmt, addressStmt). Only
resource handling changes: the queries, parameters, messages and the
catch block each exception reaches are the same as before.

SessionManagement2To5PoolLeakIT calls each servlet five times and checks
every response came from the database.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ismisepaul ismisepaul added this to the 4.0.0 milestone Oct 25, 2026
Copilot AI balanced review requested due to automatic review settings October 25, 2026 00:59
@ismisepaul ismisepaul moved this from Backlog to Next Release Backlog in Security Shepherd Oct 25, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The narrowly scoped resource cleanup preserves challenge logic, includes targeted regression tests, and has no identified blocking issues.

No open issues 🎉

What changed in this PR

Addresses part of #857 by preventing connection-pool exhaustion in Session Management challenges 2, 3, and 5 while preserving their intentionally vulnerable behavior.

Changes:

  • Converts JDBC connections, statements, and result sets to try-with-resources across seven servlets.
  • Preserves existing SQL, parameters, commit order, and challenge responses.
  • Adds regression tests that call each servlet five times, exceeding the three-connection pool capacity.
File Description
src/​main/​java/​servlets/​module/​challenge/​SessionManagement5SetToken.java Closes token-request lookup resources automatically.
src/​main/​java/​servlets/​module/​challenge/​SessionManagement5ChangePassword.java Returns previously leaked password-change connections.
src/​main/​java/​servlets/​module/​challenge/​SessionManagement5.java Closes login lookup and authentication resources.
src/​main/​java/​servlets/​module/​challenge/​SessionManagement3ChangePassword.java Returns previously leaked password-change connections.
src/​main/​java/​servlets/​module/​challenge/​SessionManagement3.java Closes login lookup and authentication resources.
src/​main/​java/​servlets/​module/​challenge/​SessionManagement2ChangePassword.java Closes password-reset resources on all execution paths.
src/​main/​java/​servlets/​module/​challenge/​SessionManagement2.java Closes authentication and address-lookup resources.
src/​it/​java/​servlets/​module/​challenge/​SessionManagement2To5PoolLeakIT.java Adds repeated-request pool-exhaustion regression tests.

Review effort: Balanced

@ismisepaul ismisepaul added the Needs Manual Testing Must be tested by hand from the PR's branch (steps in the PR) before merging label Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Bug Levels Needs Manual Testing Must be tested by hand from the PR's branch (steps in the PR) before merging

Projects

Status: Next Release Backlog

Development

Successfully merging this pull request may close these issues.

2 participants