Rails user switches session - ruby-on-rails

I've got a Rails application running and it seems that every once in a while a user gets the cookie session_id value from a different user.
I use active_record_store to keep track of the session in Rails.
The current_user method:
def current_user
#current_user ||= session[:user_id] ? User.find_by_id(session[:user_id]) : nil
return #current_user
end
I run 8 ruby processes on a Windows machine using Apache 2.2.15. Sometimes it serves the incorrect session_id to the user. My rails version is 2.1.2
In the log file I can see the user changes session_id of a different user.
For instance:
Processing Manage::TruckController#show (for 179.34.103.8 at 2011-05-12 07:35:24) [POST]
Session ID: 1fbc801bbade1007291901ca810bfeda1eab76
....
Completed
And 5 minutes later is would get a different session id, however belonging to a valid user.
Processing Manage::TruckController#edit (for 179.34.103.8 at 2011-05-12 07:40:01) [POST]
Session ID: 2f8e84c40c490c509feabbce9701aa9101ba0f
....
Completed
To me this seems that Rails is handing out incorrect session_id data to the cookie that is stored on the web browser of the user.
Any suggestions on this?

From looking at the code and
the security guide, it seems like there is a slight possibility of MD5 collision. It's very unlikely that this would happen or be reproducible though, so I'm more inclined to say it has something to do with the browser testing.
I'd first make sure that your browser isn't serving up these bad session IDs by using a tool like Charles.
I also recommend using the cookie session whenever possible which would avoid this sort of problem.
Finally, since you're running a fairly old version of Rails it might be worth trying an upgrade. It's possible you're hitting an old bug.

I found this extremely useful.
how-do-i-prevent-rails-users-from-accidentally-authenticating-as-the-wrong-user
If you are:
destroying your database in development
AND
using the out-of-the-box Rails secret_token.rb
The client browser will have preserved a valid session containing a user_id that may or may not belong to that user.
I had a similar issue and resolved it using a code snippet similar to
this comment by mdesantis on managing Rails secret token

Related

How does rails/devise handle cookie sessions?

I'd like to understand what's really going on when signing in a user with rails/devise.
I've created a minimal rails app, installed devise and created a User devise model.
Everything works fine, and when I log in (using remember me) I get a session cookie just as expected.
Now what's bugging me is : How does rails handle the session informations that the browser is passing through the cookie ?
I'd naively expect some information to be stored in the database, but I don't see where. There's no such thing as session table, no session column in Users, and I couldn't find anything of interest in the tmp dir.
Note that restarting the server wouldn't kill my session. It is of course expected, but now I'm really wondering what kind of magic is happening here ?
in other words : how does the server check the validity of a cookie to authenticate a user ?
Thanks !
The default rails session storage is CookieStore. This means that all the session data is stored in a cookie rather than in the database anywhere. In Rails 3.2 the cookie is signed to prevent tampering, but not encrypted. In Rails 4 it's generally encrypted by default. The fact that it's in a cookie is how it persists across restarts of your server. It also means you can only store 4k of data and you wouldn't want to store anything sensitive in there in Rails < 4. It's best to keep a minimum of data in the session anyway.
You can also opt for storing the session data in the database and only having a session id in a cookie.
This answer I gave the other week has some extra info that might be useful:
Sessions made sense to me before I started reading about them online
Also, the rails api doc for CookieStore gives a nice summary:
http://api.rubyonrails.org/classes/ActionDispatch/Session/CookieStore.html

Rails sessions not saving

I'm in the process of upgrading a Rails app from Rails 2 directly to Rails 4. I'm using the new /config/initializers/session_store.rb file, with CookieStore, but for some reason my sessions are not saving.
When trying to do something along the lines of
render :text => "#{request.session_options[:id]}"
I get a new session ID every refresh.
I've tried on different browsers, and all should be accepting cookies.
I have no idea what's going on. Why won't these sessions persist?!
Edit: thank you all for your suggestions. Here's a little more information, and a few things I've noticed:
First, about my set up -- I'm running the server with Rails 4/Ruby 2 through RVM on an Ubuntu VM on my Windows 7 machine.
Although I'm upgrading from Rails 2, that only really applies to the models/controllers/views/etc -- I generated a new Rails 4 application for all of the supporting infrastructure.
I created another application on the same VM that JUST sets a session and then displays, and that works fine.
What the session is storing varies slightly depending on what the user is doing, but usually it holds simply a user id (just an integer), and occasionally a little more -- (i first noticed this manifesting itself while trying to pass an OAuth token from the OAuth gem.)
I've noticed that if the VM's system clock falls behind the Windows 7 host machine clock, the user id sessions hold. That causes other problems, especially with OAuth, but there seems to just be a time issue somewhere. I've tried doing things like removing the time zone from my environments/development.rb, but that did not help.
As a general answer a couple of possible problems are
Session size over 4K limit (which is apparently the case).
CookieOverflow is raised if you attempt to store more than 4K of data.
Please, bear in mind that if you store an object in session, the object is previously serialized before storing it and its size would be bigger. More info on the general problem and possible solutions for the specific problem, here.
Problems with CSRF protection.
If the security token doesn't match what was expected, the session
will be reset
Edit: To check if it is a CSRF case, you can, as Abdo comments below, temporarily disable the protect_from_forgery line in ApplicationController
I had a similar symptoms. It turns out it was because I added the rails-api gem and it totally broke session saving.
From: Railscasts Episode 415 Upgrading to Rails 4
There’s one more configuration change we need to make, in the secret
token initializer. In Rails 4 the configuration option in this file
has been renamed from secret_token to secret_key_base. We’ll need to
specify both options while we’re transitioning from Rails 3 but once
we’ve successfully migrated our application we can remove the
secret_token option. It’s best to use a different token for our
secret_key_base.
This is necessary because we’re moving from a serialized cookie stored
on the client to an encrypted cookie. This prevents users from easily
being able to see the contents of their session cookies.
The episode includes a very good series of tips regarding upgrading from 2 to 4 and I was able to do that successfully using this tutorial.

Rails session id is nil

I've got a Rails 2.3.5 application that I'm migrating to Rails 3.0.10 that's run into a problem with sessions.
Some code is failing during integration tests because the session has no id (request.session is an empty hash, and request.session_options[:id] is nil). We are currently using webrat, but the same thing happens with capybara and with standard rails helpers. Sessions do seem to be set up properly, since some of the integration tests have session ids. It looks like the session id is missing only in tests that don't log in before trying to access the session id (i.e. most of them).
I've tried switching the session backend (it's currently cookie based) to ActiveRecord, but that didn't help. I've created a new Rails 3.0.10 app, and it also has nil session ids. I've even dug into Rails's session handling, and it looks like there's no session id being generated on if a session is missing one.
Is this lack of session ids expected behavior that's documented somewhere? If it's a bug, is there a version of Rails that generates session ids properly?
The only way I've seen how to solve this is to prime the sessions.
sid1 = session[:session_id]
sid2 = request.session_options[:id]
However, if for some reason the session cookie is deleted, it can still happen.
I tried that and no result. I also tried session[:foo] = 'bar' as I liked the way it looked better but still no result.
I rebooted and still no joy. Then I went into my browser settings and deleted my cookies. That fixed it. From this experience it appears a cookie can keep sessions from being forced. I had been changing class names and changing my database tables. Somehow I had corrupted my cookie.

Rails 3 application creates sessions only for certain users in my db

This is an extremely weird situation. I have a Rails 3 app that authenticates users using OmniAuth. The problem I recently encountered is that after correctly validating a user using the aforementioned gem, at some part of the code I set some session variables, specifically:
session[:user_id] = user.id
The problem is, that this line only works for some users (it does not depend on the browser, the cookies, nothing, only for certain users. The user variable is valid and has an id attribute, but this session variable does not persist on the next request, sending this user back to the login page. Again, this only happens to some users, which makes the problem a whole lot more difficult to debug.
Any ideas? Thanks in advance!
PS: I've tried using the cookie session store and the database session store, both with the same results.
EDIT: The problem ended up being something completely not related to sessions.

Inadvertent Session Hijacking Issue With Restful Authentication

I'm using the current version of restful_authentication that is found on github and I'm having a bunch of strange session issues. The server seems to be somehow assigning sessions to users it shouldn't be. This only happens when crossing the logged out/logged in barrier.
Here's an example. With no sessions active on the server, I log in to an account with user A. On another machine, I log in with user B. Then when logging out of user B, sometime after the logout redirect happens, I will be logged in as user A. From this point, I can continue to navigate the site as if I had logged in as that user! Something I've observed via the logs is that when this hijack happens, the session IDs are not the same. User A is logged in in both sessions, but the session ID's are completely different. This is just one example of what might happen. I can't reproduce the issue reliably as it is seemingly random.
It doesn't seem to be a symptom of the environment or the server it's running on. I can reproduce the problem using both mongrel and passenger. I've also seen it in development and production. I am using db-based sessions in this application and it is running on Rails 2.1.1. I applied the stateful option when calling the generator. Otherwise no other modifications have been made to how sessions are handled.
Update
Here is the offending method which came directly from restful_authentication.
# Accesses the current user from the session.
# Future calls avoid the database because nil is not equal to false.
def current_user
#current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless #current_user == false
end
This can happen if you (or those who wrote restful_authentication) are caching the current user in a class variable. I've seen a bunch of articles advocating the use of "User.current_user", but since classes are cached across requests, this can cause session tainting.
I don't know if this is so much of an answer as it is a work around. All I did was switch over to cookie based sessions and everything is working smoothly.
Is this site remote? Are you logging into it onto two separate computers on the same network?

Resources