In rails we have something called secret_key_base in config/secrets.yml
What if this production secret is accidentally shared via GitHub (public repo)
What's the worst thing a hacker can do?
Can salted passwords in the users table leak as a result...
Rails by default uses browser cookies as its session store. This means that as opposed to the traditional way of storing session data on the server and only a session id in the cookie, Rails stores the whole session data in the cookie.
This of course would not be very secure in many cases, any user could just see and modify his session contents. So the cookie in Rails is encrypted and signed. The key used for this (encryption and integrity verification) is in secret_key_base.
What this practically means is if this secret_key_base is compromised, any user can decrypt, modify and reencrypt his session cookie (all the data in the session). In some applications this causes no problem as there is nothing interesting stored in the session anyway. But in most cases, it leads to all kinds of problems depending on the actual business logic. For example if privileges were stored in the session, a user could change his privileges in the application, probably an unintended result.
Note that if you use a different session store (like for example Redis), you don't need this secret. Afaik it's only used to encrypt cookies if the cookie store is used for sessions. Using a server-side session store is a good idea and the best practice anyway as it is more secure.
Related
I have two models doing login (Devise) in my Rails app - Admin and User, both currently use the default cookie store for session data.
I want to be able to identify an Admin session in AJAX requests coming in from the admin, for authorization of these API calls. I plan to do this by setting an encrypted cookie upon Admin login. When the AJAX API call comes in, I open the cookie, grab some identification from it and look for a matching existing Admin session in the store.
As I understand it, to do this, I must have session information stored in the back-end, either by DB or memcache stores.
I expect to have millions of sessions of Users and just a few sessions of Admin at any given time. For this reason, I don't want to just move all session information to a DB or memory, since this is a heap of unneeded data to store. I only want to store/look at Admin session data.
A solution will be creating some custom model which enumerates Admin user sessions, and is maintained by the app. This is simple enough but requires for instance, a way to clean up sessions when they die without signing out. Essentially this is an attempt to duplicate Rails's session store mechanism, which comes with all the problems of storing and maintaining sessions. Instinct tells me to avoid this solution. Am I correct to avoid it?
If so, then my question is, is there a way to configure multiple session stores in a Rails app, a different store for every logged in Model? In this case, have Admin sessions stored in memory, and User sessions stored in cookie. If not, I'll greatly appreciate any comments and suggestions.
Thanks!
You may be thinking about it wrong.
Session are a low level mechanism that you build your authentication on top of. Its just a cookie containing an identifier (a random hash) which is linked to a session storage (by default cookies). This is a simple mechanism to add persistence to a stateless protocol.
Confusingly we also use the concept "sessions" when talking about authentication - for example logging a user in is often referred to as "creating a session". This is complete poppycock as we are just storing a claim (often a user id) in the session that was created when the user first visits the application.
If so, then my question is, is there a way to configure multiple
session stores in a Rails app, a different store for every logged in
Model?
No. Thats a chicken-vs-egg conundrum. In order to know which session storage to use you would need to access the session storage to know which session storage to use... you get the picture.
While you could create your own session storage mechanism that works differently does this is most likely a complete waste of time. Premature optimization is the root of all evil.
As I understand it, to do this, I must have session information stored
in the back-end, either by DB or memcache stores.
Not quite true. You can perfectly well build an authentication solution with just the cookie storage. In that case Rails just keeps a record on the server of which session identifiers are valid.
The main reason you would need to store additional session information in the database or memcached is if you need to store more data in the session than the 4093 bytes allowed by a cookie. Cookie storage is after all much faster and does the job fine 99% of the time. YAGNI.
You should also recognize that not everything needs to be saved in the session storage. For example the Devise trackable module saves log in / out timestamps on the user table as part of the process of authenticating a user. This is "session information" yet has nothing to do with session storage.
I want to be able to identify an Admin session in AJAX requests coming
in from the admin, for authorization of these API calls.
There are many ways to use different authentication logic for different parts of the application such as Warden strategies. For an API you may want to consider using stateless (and sessionless) authentication such as JWT.
I have been using Devise for a while to handle authentication on my Rails apps, but never really understood how it works. Because Devise also uses the session storage config set on Rails, I'm assuming this is a question on session handling with Rails.
Basically, I'm an auth newbie. I've read a few articles about authentication but most deal with abstracted libraries (they talk about engines, middle ware, etc) that don't make much sense to me. I'm really looking for lower level details.
Here's what I know so far..
I know about cookies and sessions. Cookies are strings stored on client-side which is used to maintain session across multiple HTTP requests.
Here's my basic understanding of authentication (please correct me if I'm wrong):
When user logs in, we send the SSL encrypted request to the server. If the credentials are valid, we save a random string called session id on the database (or any other data store) as the valid session id associated with a user id. This session id changes for each login/logout of the user.
After saving that session id on our data store, we return a response that asks the browser to set a cookie with the session id. This session id along with the user id would then be sent for successive request to the domain until it expires. For each request, our server would check the session id on the headers and verify if that session id is valid for that user id. If it is, then consider that user authenticated.
Here are my questions:
I've read that by default starting from Rails 2, it now uses CookieStore (instead of SessionStore) which generates session hashes with SHA512 (instead of session ids), and all this is stored on a cookie which means multiple user id's can literally have the same session hash and it would just work fine. It seems to me that this is a very dangerous thing, exposing a large number of hashes with a single secret key stored on the server and basing your entire authentication system based on this key. Is there a real world large scale application that uses hashing instead of storing server side session id's?
On the topic of storing active session id's on server side, I've also read that you can switch to use different kinds of session storage for Rails. Based on this, I've heard of systems moving authentication systems out as services and using auth tokens instead. What's an auth token and how does it differ from a session id?
Seems like I can just keep guessing a random string (for both hashing and server side sessions) to grab an existing session. Is there a way to protect against this? Is it normal to use more values stored on a cookie? (such as the username, real name or even another hash for authentication)
I know I'm asking a lot but I believe this will be useful for people like me who do not understand authentication and will be very useful to get a solid foundation about the topic.
I've read that by default starting from Rails 2, it now uses
CookieStore (instead of SessionStore) which generates session hashes
with SHA512 (instead of session ids), and all this is stored on a
cookie which means multiple user id's can literally have the same
session hash and it would just work fine. It seems to me that this is
a very dangerous thing, exposing a large number of hashes with a
single secret key stored on the server and basing your entire
authentication system based on this key.
Yeah, it seems scary at first blush, but I'm not sure what the danger really is. In Rails 4, session data is encrypted using PBKBF2, and then signed with your session secret. This signing helps detect if the contents of the encrypted session have been tampered and the server will reject the session if it detects tampering.
https://cowbell-labs.com/2013-04-10-decrypt-rails-4-session.html
If someone gains access to the session token (which is used to sign the session cookie), you likely have much bigger problems on your hands than end-users attempting to impersonate the wrong user.
Is there a real world large scale application that uses hashing
instead of storing server side session id's?
I honestly don't know the answer to this one offhand, but I suspect that the fact that this is the "default" for Rails means that there are more than a handful of sites out there using cookie session stores.
On the topic of storing active session id's on server side, I've also
read that you can switch to use different kinds of session storage for
Rails. Based on this, I've heard of systems moving authentication
systems out as services and using auth tokens instead. What's an auth
token and how does it differ from a session id?
I'm doing this on a server now - basically a random hash is generated when a user authenticates, and that hash is stored, encrypted and signed, in the cookie. The cookie hash is a key into a server-side datastore (in my case Redis, but it can be in a relational database or memcache or whatever you like), and the actual session data is the stored server-side mapped to that key. This leaves less of your session data in the hands of the client were people could potentially decrypt and analyze it, so it's generally a bit safer.
Seems like I can just keep guessing a random string (for both hashing
and server side sessions) to grab an existing session. Is there a way
to protect against this? Is it normal to use more values stored on a
cookie? (such as the username, real name or even another hash for
authentication)
Yes, you could do that, but it would take a very very long time. You would also need to guess how to sign the newly tampered cookie data so that it'd match what the server expects to see on its side, and it's signed with a pretty large key.
I really don't think there's much alternative for persisting authentication state to using cookies (I suppose HTML5 Local Storage would work if you're feeling exotic and don't care much about legacy browser support).
I would like to know in Rails
what is the difference between
ActionDispatch::Sessions::CookieStore and ActionDispatch::Sessions::CacheStore
For CacheStore, i assume Rails store the session in memory(RAM)?
What about CookieStore, where are they storing?
Kit
CookieStore is stored in the client's browser as a cookie. The cookie is signed with your application's secret key so theoretically they should not be able to tamper with it. See here for more information.
CacheStore is stored in whatever ActiveSupport::Cache::Store is using to store information (i.e. memcached or redis, on the server side not on the client side). See here for more information.
I was trying to find the location of session values store in redmine. When a user is login, where does its information goes that has been stored in session.
Redmine stores session data in a cookie (as is the default in Rails apps in general). As such, there is no actual session data stored on the server.
The session data in the cookies are cryptographically signed in a way that actual end users can not change them. However, the information is visible to them which means that you shouldn't store sensitive (or large amounts of) data in there.
Coincidentally, this is also why you need to create the session secret when you first install Redmine. It is used to sign the cookie and to ensure that the data wasn't tampered with.
Not sure to understand the question but if you want to access the session variable you can do:
session[:foo]
I was wondering whether there is any difference between a session and an encrypted cookie (configured to expire as the session cookie does).
Aren't they the exact same thing? Or Rails provides extra security for sessions?
A session is a higher-level thing than a cookie. Sessions are collections of variables which persist for one user session only. Sessions can be stored in a cookie, in a database, or wherever a session-handling plugin chooses to store them. Cookies are now the default place where sessions are stored in modern versions of Rails. Note: when sessions are stored outside the cookie, there's an ID stored in the cookie so Rails can look up the session data in wherever it's stored (e.g. a database).
Now, let me move on to what I think you want to be asking: what's the difference between Rails' default session-storage (which uses an un-encrypted cookie) and Phusion's EncryptedCookieStore or any other encrypted-cookie session storage implementation? Why do you care about encrypting a session cookie?
According to http://agilewebdevelopment.com/plugins/encrypted_cookie_store, here's the crux of the difference: "EncryptedCookieStore is similar to Ruby on Rails's CookieStore (it saves session data in a cookie), but it uses encryption so that people can't read what's in the session data. This makes it possible to store sensitive data in the session.".
Note that there are multiple different EncryptedCookieStore's. AFAIK, you's want to use Phusion's EncryptedCookieStore and not ThinkRelevance's older EncryptedCookieStore.
If you're not encrypting cookies, then session data is easily readable by anyone with access to the cookie (either via network sniffer, disk access to the client, XSS, etc.) For details about how session vars are stored into cookies (along with security implications), look here: http://www.neeraj.name/2009/05/04/how-cookie-stores-session-data-in-rails.html.
Note that the default (non-encrytped) cookie storage is tamper-resistant (meaning Rails will reject a maliciously changed cookie). So if all you're worried about is preventing people from changing your cookies (but don't care if they see your cookies) then you're OK with the default.