Skip to content

Commit

Permalink
Move secure migration into a rake task
Browse files Browse the repository at this point in the history
  • Loading branch information
sikachu committed Mar 10, 2021
1 parent 1973f37 commit c23358c
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 30 deletions.
44 changes: 14 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,43 +112,27 @@ information into the log, and it is required for security reason.
CVE-2015-9284 mitigation
--------------

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

[CVE-2019-25025]: https://github.com/advisories/GHSA-cvw2-xj8r-mjf7
[#151]: https://github.com/rails/activerecord-session_store/pull/151

However, as long those sessions exist in your database you are still affected
by the security issue. Therefore it is strongly recommended not to rely on the
fallback but to actively migrate the insecurely stored session IDs by calling
the `#secure!` method on all sessions.

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

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

```ruby
# db/migrate/20210310083511_cve201925025_mitigation.rb
class Cve201925025Mitigation < ActiveRecord::Migration[5.2]
def up
ActionDispatch::Session::ActiveRecordStore.session_class.find_each(&:secure!)
end

def down
# no-op
end
end
```console
$ rake db:sessions:upgrade
```

After `rails db:migrate` is performed, the session IDs are stored in the
securely hashed format provided by `Rack::Session::SessionId` and no longer
vulnerable to CVE-2019-25025.
This rake task is idempotent and can be run multiple times, and session data of
users will remain intact.

Please see [#151] for more details.

[#151]: https://github.com/rails/activerecord-session_store/pull/151

Contributing to Active Record Session Store
--------------
Expand Down
5 changes: 5 additions & 0 deletions lib/tasks/database.rake
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,9 @@ namespace 'db:sessions' do
where("updated_at < ?", cutoff_period).
delete_all
end

desc "Upgrade current sessions in the database to the secure version"
task :upgrade => [:environment, 'db:load_config'] do
ActionDispatch::Session::ActiveRecordStore.session_class.find_each(&:secure!)
end
end
11 changes: 11 additions & 0 deletions test/tasks/database_rake_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,17 @@ def test_trim_task
assert_equal 0, old_session_count
assert_equal retained_session, recent_session
end

def test_upgrade_task
Session.create!(session_id: "original_session_id", data: "data")
Session.create!(session_id: "2::secure_session_id", data: "data")

Rake.application.invoke_task 'db:sessions:upgrade'

assert_nil Session.find_by_session_id("original_session_id")
assert Session.find_by_session_id(Rack::Session::SessionId.new("original_session_id").private_id)
assert Session.find_by_session_id("2::secure_session_id")
end
end
end
end

0 comments on commit c23358c

Please sign in to comment.