mongoid/mongo_session_store

Using more random session ids -- security issue

tombruijn opened this issue · 0 comments

The current implementation of the gem sets the session_id of the session in a cookie in plain text. A person could sign in as a any user as long as they know the session id and set a cookie with this id.

// Paste in console of a browser that's not signed in
// and replace {session_id} with the contents of your browser's _session_id cookie
document.cookie="_session_id={session_id}; path=/";

This upon itself is an issue. It gets worse because the session id generated is using BSON::ObjectId. BSON::ObjectId is mostly sequential and would be guessable or at least bruteforceable. https://docs.mongodb.com/v3.2/reference/method/ObjectId/

Solutions

Use more random session_ids

We could favor SecureRandom.uuid for generating session ids, even use it in combination with MongoDB uuids. Or use what Rails uses as a default SecureRandom.hex(16). These alternative primary keys are more random, could still theoretically be bruteforcable, but very unlikely.

Using non optimized data types increases the index size, but does still work and enforces a unique primary key for the document collection.

This approach is used by the activerecord-session_store and sequel-rails alternatives.

Encrypted cookies

Save the session id encrypted in a cookie. This makes it difficult for potential hackers to modify cookie contents. They will still be able to see how the session id is generated in the gem's source code, but can't guess the sequence because the session id is encrypted.

We can use encrypted cookies as Rails does by adding the logic from the Rails encrypted CookieStore.

This uses the secret_token and secret_key_base values as saved in config/initializers/secret_token.rb for encryption.

This adds quite a bit more code to the code base and requires additional testing of course. I would copy most of the tests from the Rails test suite.

WDYT?

WDYT? Let me know what options we favor?
Personally I'm even thinking of using both. Starting with just "Use more random session_ids" and adding encrypted cookies later.