Rails 3 user session gets destroyed while calling create from backbone collection - ruby-on-rails

I have a backbone app which is being fed data by a Rails backend.
When trying to call create from Backbone collection, the session in rails gets destroyed.
Any pointers on how to overcome it?

This sort of thing is almost always a result of a bad or non-existent CSRF token. In recent versions of Rails 3.0.4+, any request that doesn't have a CSRF token that matches the token generated for the users current session will destroy the session as a security measure.
Here is some more info on CSRF security in Rails:
http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf
You can easily test to see if this is what is causing your problem by commenting out the protect_from_forgery method call (probably in your application_controller.rb file). But I wouldn't recommend disabling it permanently for security reasons.

Related

rails - What is the biggest security risk in intentionally disabling a CSRF check on the 'create' action?

I have a fully working product on Rails 5. I now wish to make a Chrome extension, using which users can create an 'Article'.
However, requests from my Chrome extension will be treated as Cross Site by my rails app. Hence, I was thinking of not doing the CSRF check at all on just my create action.
What is the biggest security risk associated with this? I understand after this, anyone will be able to make POST request to my server that creates a new article - however, this is not a damaging action like update, or worse, delete.
The Rails guide states that,
CSRF attack method works by including malicious code or a link in a
page that accesses a web application that the user is believed to have
authenticated. If the session for that web application has not timed
out, an attacker may execute unauthorized commands.
If a CSRF token is a valid one, it is a kind of assurance that the user session has not been hijacked and the request has been made with the user consent.
For more info, I recommend you to refer the Rails guide http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf

Turn on request forgery protection with or witout Rails's protect_from_forgery?

I building a REST API based on Rails 4.
To prevent from cross-site request forgery attacks, I added a CSRF token inside a custom HTTP header that is needed to perform requests such as POST, DELETE, etc.
I know Rails 4 also provides a protect_from_forgery method with a special option for APIs: with: :null_session.
So I think that, given it's a best practice, this new Rails method should be present at the top of my ApplicationController.
But in the same time, I'm also wondering why I should add it... if it is not necessary. Because as I said, my requiring a CSRF token inside a custom HTTP header.
Could you give me the benefits of adding this Rails feature? Thanks a lot.
protect_form_forgery just adds a before action to the controller which checks if the authenticity_token is valid.
The :with parameter specifies how the controller should behave if the token is invalid.
with: :exception: raises an exception in the controller which can by catched.
with: :null_session: resets the session itself. This means the complete session will be deleted. In other words the session cookie will be reset. For example an user_id stored in the session won't be available anymore (puts session[:user_id] # => nil). So you always have to provide a token or any other authentication, which is perfectly fine for an API.
You can also remove protect_from_forgery if you don't use session.

Switching out authlogic from rails app. Session is missing from post requests

I was using authlogic on my Rails app and decided to remove it in favor of implementing 3rd party authentication using OAuth. Switching to to this approach has left me with a very interesting problem:
The rails session object is empty when I make a post request from the app. A 'get' request always has the session populated but not a post. I can verify that it is indeed posting the session cookie in both cases but dont see why this is happening.
Any ideas why this is happening or tips to debug this?
This is because the posts were missing the csrf token. For some reason, Authlogic takes care of the CSRF verification for AJAX posts.

Rails API design without disabling CSRF protection

Back in February 2011, Rails was changed to require the CSRF token for all non-GET requests, even those for an API endpoint. I understand the explanation for why this is an important change for browser requests, but that blog post does not offer any advice for how an API should handle the change.
I am not interested in disabling CSRF protection for certain actions.
How are APIs supposed to deal with this change? Is the expectation that an API client makes a GET request to the API to get a CSRF token, then includes that token in every request during that session?
It appears that the token does not change from one POST to another. Is it safe to assume that the token will not change for the duration of the session?
I don't relish the extra error handling when the session expires, but I suppose it is better than having to GET a token before every POST/PUT/DELETE request.
Old question but security is important enough that I feel it deserves a complete answer. As discussed in this question there are still some risk of CSRF even with APIs. Yes browsers are supposed to guard against this by default, but as you don't have complete control of the browser and plugins the user has installed, it's should still be considered a best practice to protect against CSRF in your API.
The way I've seen it done sometimes is to parse the CSRF meta tag from the HTML page itself. I don't really like this though as it doesn't fit well with the way a lot of single page + API apps work today and I feel the CSRF token should be sent in every request regardless of whether it's HTML, JSON or XML.
So I'd suggest instead passing a CSRF token as a cookie or header value via an after filter for all requests. The API can simply re-submit that back as a header value of X-CSRF-Token which Rails already checks.
This is how I did it with AngularJS:
# In my ApplicationController
after_filter :set_csrf_cookie
def set_csrf_cookie
if protect_against_forgery?
cookies['XSRF-TOKEN'] = form_authenticity_token
end
end
AngularJS automatically looks for a cookie named XSRF-TOKEN but feel free to name it anything you want for your purposes. Then when you submit a POST/PUT/DELETE you should to set the header property X-CSRF-Token which Rails automatically looks for.
Unfortunately, AngualrJS already sends back the XSRF-TOKEN cookie in a header value of X-XSRF-TOKEN. It's easy to override Rails' default behaviour to accomodate this in ApplicationController like this:
protected
def verified_request?
super || form_authenticity_token == request.headers['X-XSRF-TOKEN']
end
For Rails 4.2 there is a built in helper now for validating CSRF that should be used.
protected
def verified_request?
super || valid_authenticity_token?(session, request.headers['X-XSRF-TOKEN'])
end
I hope that's helpful.
EDIT: In a discussion on this for a Rails pull-request I submitted it came out that passing the CSRF token through the API for login is a particularly bad practice (e.g., someone could create third-party login for your site that uses user credentials instead of tokens). So cavet emptor. It's up to you to decide how concerned you are about that for your application. In this case you could still use the above approach but only send back the CSRF cookie to a browser that already has an authenticated session and not for every request. This will prevent submitting a valid login without using the CSRF meta tag.
Rails works with the 'secure by default' convention. Cross-Site or Cross-Session Request Forgery requires a user to have a browser and another trusted website. This is not relevant for APIs, since they don't run in the browser and don't maintain any session. Therefore, you should disable CSRF for APIs.
Of course, you should protect your API by requiring HTTP Authentication or a custom implemented API token or OAuth solution.

rails csrf token lifetime

I use Rails request_forgery_protection mechanism to protect my POST actions from CSRF attacks and captcha to protect the GET actions. This way if someone stages a two-phase attack within one session, GET-ting the form with the current token and then POST-ing a forged request with that token, he will eventually be faced with a captcha check.
I'm stuck with that though, because Rails doesn't regenerate the CSRF token until the end of session. That doesn't seem right to me, I'd think the token should be renewed before the next action. I'm wondering maybe I have tweaked something wrong? Is there another way of doing this?
Thanks.
I've not sure if this is a good idea or not, but you can nil out the token yourself on get requests from inside your application controller.
before_filter :reset_csrf
private
def reset_csrf
session[:_csrf_token] = nil if request.get?
end
In case form token is NOT regenerated for each page request, this protection is bad. I faced it sometime ago (when testing Redmine, which is RoR-based) and reported this issue, but didn't retested it.
If it's still not regenerated, I suggest you report this to RoR team.

Resources