There is an issue our team identified that is worth filing a bug for (or at least, we think it’s an issue), but it’s non-obvious what project to which it should be filed, so I’m asking here.
Background on sessions in Rails
When building a Rails application, you will likely need to store user session state, which the framework has a built-in mechanism to handle. Depending on product requirements, you can pick from a few stores for said session (quoting the ActionController docs):
ActionDispatch::Session::CookieStore
- Stores everything on the client.ActionDispatch::Session::CacheStore
- Stores the data in the Rails cache.ActionDispatch::Session::MemCacheStore
- Stores the data in a memcached cluster (this is a legacy implementation; consider usingCacheStore
instead).ActionDispatch::Session::ActiveRecordStore
- Stores the data in a database using Active Record (requires theactiverecord-session_store
gem)- A custom store or a store provided by a third party gem
[…]
For most stores, this ID is used to look up the session data on the server, e.g. in a database table. There is one exception, and that is the default and recommended session store - the CookieStore - which stores all session data in the cookie itself (the ID is still available to you if you need it). […].
What is an ID in Rails?
The notion of an “ID” has a fairly consistent meaning throughout Rails: an opaque identifier that can be used to identify a resource. IDs are shared in various places that one would normally not put sensitive information: URLs, logs, error messages, etc. Getting an ID is never enough to get
What is the problem?
Session stores besides CookieStore
make session IDs violate the common understanding of an “ID” in Rails. While Rails famously provides collection of sharp knives, this is more of a misunderstanding-in-the-making than a sharp tool in and of itself. Making things worse, the notion of session IDs being dangerous (while noted at length in the docs), are only dangerous for stores other than the default. Meaning, one can make many references to a session ID in insecure contexts without issue if using the default store, but changing your store suddenly makes all of those references highly problematic.
Even worse, the various patches that addressed CVE-2019-16782 made things more confusing, introducing the notion of a “session public ID” and “session private ID”. One could very reasonably assume that a “public ID” is non-sensitive/freely shareable while “private ID” is an important secret, as is the case in asymmetric cryptography (commonplace in web-dev). In reality, unless you have direct session store access (e.g. access to your relational database of choice if using ActiveRecordStore
), the reverse is true: a “public ID” is the dangerous secret value while the “private ID” is mostly harmless.
Suggested solution
Change the mechanics of stores (besides CookieStore
) to have both a session ID (which becomes the value of an opaque identifier that is harmless for impersonation on its own) and a session token (which is the important secret value). The public vs. private distinction could be similarly migrated to be named “token” vs. “token digest” or something similar.