I am working on a Rails app that recently went through a security audit, and one of the issues they came up with is that if the user gets the "session_id" from another users cookie, he is able to log in as that user. Is it possible to prevent this? How would I do it with my current setup?
Rails 3.2.12
devise (2.1.2)
My config/initializers/session_store.rb is
MyApp::Application.config.tap do |config|
config.session_store :active_record_store, config.session_options
end
Force SSL is enabled on production
config.force_ssl = true
I looked at Rails 4 Encrypted Cookie Replay Attack but since mine is using active record for sessions, not sure I can do the same.
I tried to add :session_limitable from Devise security extension, but it appears to be doing something else altogether.
To quote the security test result
Mitigate session replaying by ensuring that only 1 login is active at a time. -- able to login as another user just by changing the "_session_id" cookie
Related
We have a setup in a way that currently some pages are being served by a Rails 4 app and a Rails 5 app. All the authentication logic resides in the Rails 4 app and we are using Devise for authentication. The session_store.rb on the Rails 4 app looks like this Rails.application.config.session_store :cookie_store, key: '_app_store'. I want to have the current_user accessible in the Rails 5 app as well. Note: Both the apps are under the same domain. Also how should I go about setting devise on my Rails 5 app so that current_user is accessible.
First allow cookie to apply for all of your subdomains:
Rails.application.config.session_store :cookie_store, key: '_app_store', domain: :all
When the browser accesses a website, the website tells the browser to set a cookie. When this happens, it specifies the cookie name, value, domain, and path.
:domain => :all makes a dot in front of the cookie domain (which is whatever host your browser has browsed to), so the cookie applies to all subdomains.
Another good thread about this topic can be found here:
https://stackoverflow.com/a/4065929/1625253
Running Windows 8 with Rubystack, Ruby 2.0.0p353, Rails 4.0.3. Built own application using Rails Composer including Devise, CanCan and Rolify. Trying to configure remember_me to be set on every user except admins and have those users remain logged in basically forever. Seems to be working in the code, but I'd like to see what the cookie is saying. I haven't yet worked with cookies and am looking for a thread to pull to unravel that mystery.
I add this code to app/models/user.rb to set remember_me:
def remember_me
true unless self.admin?
end
In config/initializers/devise.rb, I set the following variables:
config.remember_for = 10.years
config.extend_remember_period = true
Users with standard user role have the PostgreSQL column remember_create_at set as long as they are logged in. It is cleared when they logout. Users with admin role never have this column set. That seems right.
I just cannot get my head around checking the cookie out. I believe it should have remember_me information in it so that the standard role user remains logged in across browser sessions? How can I dig that information out and verify it? Thanks...
Are you just trying to inspect the cookies on the browser side? Firebug has a cookies tab for that, and if you're using Chrome, you can view them under Resources > Cookies in the web development tool.
At some mystery point X with this rails app hosted on heroku, a logged in user would suddenly be logged in as another user. I am using the devise gem for authentication.
This has occurred for 2 users that we know of. I am currently tracking down what the root cause of this issue could be.
What I need to do right now is invalidate all devise sessions in order to force users to login again. After a user logs in, the problem seems to go away.
I tried reseting my secret_token but I was not forced to login again. I then scaled my web dynos down and then back up. I also restarted the app. All trying to get the secret_token change to reset the sessions.
Any other ideas?
You should be able to change your session cookie name to invalidate all sessions, which lives in config/initializers/session_store.rb
YourApp::Application.config.session_store :cookie_store, key: '_change_me_session'
Changing your session_token will work if you're storing your sessions in cookies (default).
But if you're storing in active_record, then you can delete all the sessions by:
rake db:sessions:clear
then: BAM! no more sessions.
Update on the accepted answer, now it is
rake tmp:clear
rake -T
...
rake tmp:create # Creates tmp directories for sessions, cache, sockets, and pids
If your sessions don't store any other critical information, you could clear the sessions:
rake db:sessions:clear
Devise has a thing called timeoutable can you work with that?
Check out
module ClassMethods
Devise::Models.config(self, :timeout_in)
end
I'm just guessing that you could do something like:
User.all.each do |user|
user.timeout_in 1.second
end
But I'm not sure if this only manages new sessions.. and not existing ones?
Actually this is overly complex.. just try:
User.all.each do |user|
sign_out user
end
See this post Log out all user with Devise
to do something like this from the console you will need to check out this example and adjust it for your needs
How to sign in a user using Devise from a Rails console?
sign_out_all_scopes(lock = true) ⇒ Object
Sign out all active users or scopes. This helper is useful for signing out all roles in one click. This signs out ALL scopes in warden. Returns true if there was at least one logout and false if there was no user logged in on all scopes.
source:
http://www.rubydoc.info/github/plataformatec/devise/Devise/Controllers/SignInOut
When cookie store is used, we have to regenerate the app secret_token which is used to encrypt the cookies.
file to configure secret_token: config/initializers/secret_token.rb
bundle exec rake secret Can be used to generate a new secret token.
https://www.tigraine.at/2012/08/03/how-to-expire-all-active-sessions-in-rails-3
Try this on your controller actions.
def index
reset_session
end
Is devise vulnerable to session hijacking over a normal http:// connection? I am having trouble figuring it out from the documentation.
Yes. Rails' default way to manage sessions is susceptible to hijacking.
This is because it transmits to the client all the information the client further requires to identify itself in HTTP cookies. For the most part, anybody who can intercept the HTTP connection can assume the identity of the client from Rails' perspective.
The simplest countermeasure is to only serve your site via HTTPS and have Rails issue secure cookies, which tells the browser only to send that cookie via HTTPS. The security guide has more helpful tips.
As mentioned in this email on Devise discussion group, security setup for the application is in the domain of the main application (in this case, Rails, I assume).
Do check out the RailsCast episode - Dangers of Session Hijacking to deal with session hijacking at the Rails Application level.
Rails Security Guide's section on Session Hijacking is another must read resource.
Devise provides for forcing SSL only cookies by setting :secure => true in the config/initializers/devise.rb file of a Rails App.
is it true that Rails depend on cookies? It seems that flash is a part
of session, and session uses cookies... so when i disable cookie in
Firefox, a Rails app that was working shows
[error]
ActionController::InvalidAuthenticityToken
so is it true that for a RoR app to work, cookies are mandatory?
Update: or, to make the Rails app work again, what is the simplest way? (and if it is one server only (Apache running mod_rails), then is it easier?)
They are not mandatory, but there are some things you can't do without cookies. You can turn the authenticity tokens off as described here.
It's not mandatory to use cookies, but it is the rails default from 2.x up. Using cookies serves as a simple solution to some more difficult problems that arise when you try to store cookies in memory on multiple servers (and you get into things like sticky sessions, losing user data etc).
You can set where rails stores your session data; that is the flash and anything that's associated with the specific user. In environment.rb you can configure where you store your sessions using the config.action_controller.session_store. The options for this are: :cookie_store, :active_record_store, :p_store, :drb_store, :mem_cache_store, or :memory_store.
cookie_store is the default, if you comment the option out or remove it from environemnt.rb. It's also the most versatile. If you have multiple servers, one request for a user might come into one server, and the next request might come into a different server. In this situation, you couldn't use memory_store, as the 2nd server wouldn't know anything about the current user.
By storing session information in an encrypted cookie, there is less load on the server to store this information. The only downside is that each request to the server needs to pass the cookie (usually <1k), but it's not a noticeable difference in anything I've ever experienced.
:cookie_store, :mem_cache_store and :active_record_store are the most commonly used ones.