Skip to content

Commit c23358c

Browse files
committed
Move secure migration into a rake task
1 parent 1973f37 commit c23358c

File tree

3 files changed

+30
-30
lines changed

3 files changed

+30
-30
lines changed

README.md

+14-30
Original file line numberDiff line numberDiff line change
@@ -112,43 +112,27 @@ information into the log, and it is required for security reason.
112112
CVE-2015-9284 mitigation
113113
--------------
114114

115-
Active Record Session Store version 1.x and are affected by [CVE-2019-25025].
116-
This means an attacker can perform a timing attack against the session IDs
117-
stored in the database. This issue was resolved in version 2.0.0 thanks to
118-
[#151]. The fix contains a backwards compatibilty fallback that migrates
119-
affected sessions whenever they are used successfully.
115+
Sessions that were created by Active Record Session Store version 1.x are
116+
affected by [CVE-2019-25025]. This means an attacker can perform a timing
117+
attack against the session IDs stored in the database.
120118

121119
[CVE-2019-25025]: https://github.com/advisories/GHSA-cvw2-xj8r-mjf7
122-
[#151]: https://github.com/rails/activerecord-session_store/pull/151
123-
124-
However, as long those sessions exist in your database you are still affected
125-
by the security issue. Therefore it is strongly recommended not to rely on the
126-
fallback but to actively migrate the insecurely stored session IDs by calling
127-
the `#secure!` method on all sessions.
128120

129-
Please be aware that you need to copy/adapt this method if you're using a
130-
custom class for storing your sessions (as described earlier in the
131-
`Configuration` part of this `README`).
121+
After upgrade to version 2.0.0, you should run [`db:sessions:upgrade`] rake task
122+
to upgrade all existing session records in your database to the secured version.
132123

133-
The following example Active Record Migration will work for the default setup
134-
of this gem:
124+
[`db:sessions:upgrade`]: https://github.com/rails/activerecord-session_store/blob/master/lib/tasks/database.rake#L22
135125

136-
```ruby
137-
# db/migrate/20210310083511_cve201925025_mitigation.rb
138-
class Cve201925025Mitigation < ActiveRecord::Migration[5.2]
139-
def up
140-
ActionDispatch::Session::ActiveRecordStore.session_class.find_each(&:secure!)
141-
end
142-
143-
def down
144-
# no-op
145-
end
146-
end
126+
```console
127+
$ rake db:sessions:upgrade
147128
```
148129

149-
After `rails db:migrate` is performed, the session IDs are stored in the
150-
securely hashed format provided by `Rack::Session::SessionId` and no longer
151-
vulnerable to CVE-2019-25025.
130+
This rake task is idempotent and can be run multiple times, and session data of
131+
users will remain intact.
132+
133+
Please see [#151] for more details.
134+
135+
[#151]: https://github.com/rails/activerecord-session_store/pull/151
152136

153137
Contributing to Active Record Session Store
154138
--------------

lib/tasks/database.rake

+5
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,9 @@ namespace 'db:sessions' do
1818
where("updated_at < ?", cutoff_period).
1919
delete_all
2020
end
21+
22+
desc "Upgrade current sessions in the database to the secure version"
23+
task :upgrade => [:environment, 'db:load_config'] do
24+
ActionDispatch::Session::ActiveRecordStore.session_class.find_each(&:secure!)
25+
end
2126
end

test/tasks/database_rake_test.rb

+11
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ def test_trim_task
5252
assert_equal 0, old_session_count
5353
assert_equal retained_session, recent_session
5454
end
55+
56+
def test_upgrade_task
57+
Session.create!(session_id: "original_session_id", data: "data")
58+
Session.create!(session_id: "2::secure_session_id", data: "data")
59+
60+
Rake.application.invoke_task 'db:sessions:upgrade'
61+
62+
assert_nil Session.find_by_session_id("original_session_id")
63+
assert Session.find_by_session_id(Rack::Session::SessionId.new("original_session_id").private_id)
64+
assert Session.find_by_session_id("2::secure_session_id")
65+
end
5566
end
5667
end
5768
end

0 commit comments

Comments
 (0)