From f45853676f9e061ce8f949405969bc7b1ac651fe Mon Sep 17 00:00:00 2001 From: David Taylor Date: Mon, 15 Nov 2021 15:50:12 +0000 Subject: [PATCH] SECURITY: Ensure _forum_session cookies cannot be reused between sites (#14950) This only affects multisite Discourse instances (where multiple forums are served from a single application server). The vast majority of self-hosted Discourse forums do not fall into this category. On affected instances, this vulnerability could allow encrypted session cookies to be re-used between sites served by the same application instance. --- Gemfile.lock | 2 +- spec/integration/multisite_cookies_spec.rb | 25 ++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 spec/integration/multisite_cookies_spec.rb diff --git a/Gemfile.lock b/Gemfile.lock index bedceee218a..6cbb8202982 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -323,7 +323,7 @@ GEM activerecord (~> 6.0) concurrent-ruby railties (~> 6.0) - rails_multisite (3.1.0) + rails_multisite (4.0.0) activerecord (> 5.0, < 7) railties (> 5.0, < 7) railties (6.1.4.1) diff --git a/spec/integration/multisite_cookies_spec.rb b/spec/integration/multisite_cookies_spec.rb new file mode 100644 index 00000000000..6256eef4aa0 --- /dev/null +++ b/spec/integration/multisite_cookies_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe 'multisite', type: [:multisite, :request] do + it "works" do + get "http://test.localhost/session/csrf.json" + expect(response.status).to eq(200) + cookie = response.cookies["_forum_session"] + id1 = session["session_id"] + + get "http://test.localhost/session/csrf.json", headers: { "Cookie" => "_forum_session=#{cookie};" } + expect(response.status).to eq(200) + id2 = session["session_id"] + + expect(id1).to eq(id2) + + get "http://test2.localhost/session/csrf.json", headers: { "Cookie" => "_forum_session=#{cookie};" } + expect(response.status).to eq(200) + id3 = session["session_id"] + + # Session cookie was rejected and rotated + expect(id2).not_to eq(id3) + end +end