Repository navigation
fix: use UTC calendar for JDBC timestamp reads - #843
Conversation
SeanDuggan
left a comment
There was a problem hiding this comment.
Fix looks good, minor issue with spotless violation which has been resolved.
ismisepaul
left a comment
There was a problem hiding this comment.
Nice fix. The DbTime.UTC approach is correct and both getTimestamp (authUser + authUserSSO) are the only ones in the codebase, so the suspension-bypass bug is properly closed.
There is an open issue #841 which also looks at addressing both this, and CTF schedule gates. However, they're different mechanisms so let's get this merged in and that can be addressed in another pr (keeps this clean)
One thing before merge: this needs a regression test. CI runs on UTC, so this bug is invisible to it and can silently come back.
Suggestion: A unit test that puts the JVM in a non-UTC zone e.g. TimeZone.setDefault(US/Pacific), and assert the suspension timestamp still reads as the correct instant. So if anyone later drops the UTC calendar, CI fails immediately instead of the bug silently returning in production.
You can create it under src/test/java/utils/DbTimeTest.java
|
Added a regression test under utils/DbTimeTest that runs with a non-UTC JVM timezone and verifies the UTC calendar behavior remains correct. All tests pass locally. |
|
Thanks @Gautam-aman One thing before we merge: as written the test doesn't quite guard the bug we care about. It asserts Suggestion: instead of checking the So something like
The key is that the expected value is worked out as UTC. If the read still lands on the correct instant even though the JVM is set to US/Pacific, that proves the |
|
Updated the regression test to exercise the actual timestamp read path using a mocked ResultSet rather than asserting the UTC constant directly. The test now runs under a non-UTC JVM timezone and verifies the returned instant matches the expected UTC instant. |
Resolve conflict in Getter.java. The dev branch refactored authUser and authUserSSO for connection pooling (OWASP#816), moving the suspension reads to new locations. Re-applied the UTC calendar argument to both of dev's suspendedUntil reads: - authUser: userResult.getTimestamp(8, DbTime.UTC) - authUserSSO: userResult.getTimestamp(1, DbTime.UTC)
|
@Gautam-aman thanks for that a couple of things more (there's been a big change merged since your PR #816 so I went ahead and resolved the conflicts)
Side note: issue #841 captures some other concerns related to this - schedule gates, non-UTC ITs - not for this PR just noting here. |
|
Addressed the thread-safety concern by changing the shared UTC calendar to a |
|
@Gautam-aman thanks for sticking with this. The The What happened is the merge took your branch's older Getter.java over dev's version rather than combining them. The fix is to take dev's Getter.java as-is and re-apply just your two timestamp reads on top, I think something like Then in that file re-add only:
After that the |
|
Thanks for the review and apologies for the delay in addressing this. I was tied up with other commitments for a bit. |
Getter.java had drifted to a pre-OWASP#816 version due to a bad merge, dropping the connection-pool refactor and CachedRowSet cap. This caused the integration-test connection-exhaustion failure. Restore Getter.java from upstream/dev and re-apply only the two UTC Calendar reads for suspendedUntil, as suggested in review.
|
Addressed the latest feedback and verified all checks are now passing. Please let me know if there's anything else that should be updated; otherwise I believe this is ready for another review. Thanks again for the guidance throughout the review process. |
|
@ismisepaul please look at it whenever you have time |
ismisepaul
left a comment
There was a problem hiding this comment.
Thanks for sticking with this @Gautam-aman — a couple of things before this can go in:
suspendedUntilis written by the stored procedures from MariaDB'sNOW(), i.e. in the DB server's local time, not UTC. Reading it with a UTC calendar is only correct when the DB runs in UTC. Our default Docker setup runs MariaDB and Tomcat withTZ=Europe/Dublin. During Irish summer time that makes every suspension one hour too long, so a single wrong password locks the user out for an hour. On a US/Pacific deployment it makes suspensions 7–8 hours too short, so the lockout is bypassed. Could you move the comparison into SQL instead (e.g.SELECT ..., suspendedUntil > NOW() AS suspended ...) so the same clock writes and checks the value? That works whatever timezone the JVM or DB is in, andDbTimeis no longer needed.src/test/java/utils/DbTimeTest.javawas dropped ina77e866c, so there's no regression test anymore. With the SQL-side check, an integration test that suspends a user and then callsauthUserwhile the JVM runs in a non-UTC zone would cover it.
|
Thanks for the review. I pushed the SQL-side suspension check and regression test in e2b698d. I could not run the full suite locally because Docker and Maven Central were unavailable; I will follow up on any CI failures. |
There was a problem hiding this comment.
🟢 Approval recommended
The suspension checks align with the database clock used for suspension writes, with targeted regression coverage and no identified blocking issues.
No open issues 🎉
What changed in this PR
Fixes timezone-dependent suspension checks in password and SSO authentication. The implementation compares timestamps against the database clock rather than introducing the UTC calendar described in the PR text.
Changes:
- Evaluates suspension status in SQL using
suspendedUntil > NOW(). - Adds an integration regression test with differing database and JVM timezones.
| File | Description |
|---|---|
src/main/java/dbProcs/Getter.java |
Uses database-side suspension checks for password and SSO authentication. |
src/it/java/dbProcs/GetterAuthIT.java |
Tests suspension enforcement across mismatched timezones. |
Review effort: Balanced
ismisepaul
left a comment
There was a problem hiding this comment.
LGTM thanks for the contribution @Gautam-aman
Fixes timezone-dependent authentication bypass caused by JDBC getTimestamp() interpreting SQL DATETIME values using the JVM default timezone.
On non-UTC JVM deployments, suspended users could authenticate because suspendedUntil timestamps were interpreted incorrectly and compared against the wrong epoch time.
This PR standardizes JDBC timestamp reads using a shared UTC Calendar.
Changes:
Added shared UTC JDBC calendar utility
Suspended users are now correctly rejected during authentication regardless of JVM timezone.