[Bug 43782] New: GenerateCSRF caches token with global key causing cross-session CSRF 403 errors on Plack workers
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 Bug ID: 43782 Summary: GenerateCSRF caches token with global key causing cross-session CSRF 403 errors on Plack workers Initiative type: --- Sponsorship --- status: Product: Koha Version: Main Hardware: All OS: All Status: NEW Severity: major Priority: P5 - low Component: Templates Assignee: oleonard@myacpl.org Reporter: johan@imcode.com QA Contact: testopia@bugs.koha-community.org Target Milestone: --- Bug 35955 (commit 108c955ea) introduced caching of the CSRF token in Koha::Template::Plugin::Koha::GenerateCSRF using Koha::Cache::Memory::Lite. The cache uses a static key "CSRF-TOKEN" shared across all sessions served by a Plack worker. Because Koha::Cache::Memory::Lite is a package-level in-process hash that is NOT flushed between requests (despite what its documentation says), the cached token from the first session persists and is returned to all subsequent sessions on the same worker process. When session B receives session A's token and submits a form, CSRF validation compares the token against session B's session_id — it was generated for session A — and returns 403. Symptoms: - Intermittent "Invalid CSRF token" 403 errors - Reproducible as "first request after idle period" (e.g. every morning) - Affects both intranet login and OPAC self-checkout (sco-main.pl) - Works on the second attempt (the second request gets the correct session's token because the old cached value is still returned — but a reload generates a new session and fresh token) The 8-hour CSRF_EXPIRY_HOURS (Bug 17110) made the window smaller. After Bug 42924 increased it to 168 hours, a worker running more than ~7 days could additionally serve a near-expired token with less than 1 hour remaining. Note: Bug 18124 correctly made CSRF tokens cryptographically session-specific. The cache layer introduced by Bug 35955 bypasses that protection. The issue can be hard to reproduce, so I have been using reports from customers to piece this together. -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 Johan Larsson <johan@imcode.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Assignee|oleonard@myacpl.org |johan@imcode.com Patch complexity|--- |Small patch Status|NEW |Needs Signoff -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 --- Comment #1 from Johan Larsson <johan@imcode.com> --- Created attachment 207786 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=207786&action=edit Bug 43782: Fix GenerateCSRF cache key to be session-specific The GenerateCSRF template plugin (added by Bug 35955) cached the CSRF token under the global key 'CSRF-TOKEN', shared across all sessions served by the same Plack worker. Because Koha::Cache::Memory::Lite is a package-level in-process hash that persists across requests, the first session's token was returned to all subsequent sessions on the same worker, causing CSRF validation to fail with 403 errors. This patch: - Changes the cache key to 'CSRF-TOKEN-{session_id}' so each session gets its own cached token - Stores the token with a timestamp and rejects cached tokens with less than one hour of remaining lifetime (CSRF_EXPIRY_HOURS * 3600 - 3600 seconds) to prevent serving near-expired tokens Test plan: 1. Apply patch 2. prove t/db_dependent/Koha/Template/Plugin/Koha.t Signed-off-by: Johan Larsson <johlar@imcode.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 David Nind <david@davidnind.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Needs Signoff |Signed Off -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 David Nind <david@davidnind.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Attachment #207786|0 |1 is obsolete| | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 --- Comment #2 from David Nind <david@davidnind.com> --- Created attachment 207788 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=207788&action=edit Bug 43782: Fix GenerateCSRF cache key to be session-specific The GenerateCSRF template plugin (added by Bug 35955) cached the CSRF token under the global key 'CSRF-TOKEN', shared across all sessions served by the same Plack worker. Because Koha::Cache::Memory::Lite is a package-level in-process hash that persists across requests, the first session's token was returned to all subsequent sessions on the same worker, causing CSRF validation to fail with 403 errors. This patch: - Changes the cache key to 'CSRF-TOKEN-{session_id}' so each session gets its own cached token - Stores the token with a timestamp and rejects cached tokens with less than one hour of remaining lifetime (CSRF_EXPIRY_HOURS * 3600 - 3600 seconds) to prevent serving near-expired tokens Test plan: 1. Apply patch 2. prove t/db_dependent/Koha/Template/Plugin/Koha.t Signed-off-by: Johan Larsson <johlar@imcode.com> Signed-off-by: David Nind <david@davidnind.com> -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 Lisette Scheer <lisette@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- QA Contact|testopia@bugs.koha-communit |andrew@bywatersolutions.com |y.org | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 Andrew Fuerste-Henry <andrew@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|Signed Off |Passed QA -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 Andrew Fuerste-Henry <andrew@bywatersolutions.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Attachment #207788|0 |1 is obsolete| | -- You are receiving this mail because: You are watching all bug changes.
https://bugs.koha-community.org/bugzilla3/show_bug.cgi?id=43782 --- Comment #3 from Andrew Fuerste-Henry <andrew@bywatersolutions.com> --- Created attachment 207995 --> https://bugs.koha-community.org/bugzilla3/attachment.cgi?id=207995&action=edit Bug 43782: Fix GenerateCSRF cache key to be session-specific The GenerateCSRF template plugin (added by Bug 35955) cached the CSRF token under the global key 'CSRF-TOKEN', shared across all sessions served by the same Plack worker. Because Koha::Cache::Memory::Lite is a package-level in-process hash that persists across requests, the first session's token was returned to all subsequent sessions on the same worker, causing CSRF validation to fail with 403 errors. This patch: - Changes the cache key to 'CSRF-TOKEN-{session_id}' so each session gets its own cached token - Stores the token with a timestamp and rejects cached tokens with less than one hour of remaining lifetime (CSRF_EXPIRY_HOURS * 3600 - 3600 seconds) to prevent serving near-expired tokens Test plan: 1. Apply patch 2. prove t/db_dependent/Koha/Template/Plugin/Koha.t Signed-off-by: Johan Larsson <johlar@imcode.com> Signed-off-by: David Nind <david@davidnind.com> Signed-off-by: Andrew Fuerste Henry <andrew@bywatersolutions.com> -- You are receiving this mail because: You are watching all bug changes.
participants (1)
-
bugzilla-daemon@bugs.koha-community.org