When to skip verify_authenticity_token - ruby-on-rails

Why would people skip the verification and increase the security vulnerability of their app? Is it beneficial to disable it on pages that have only GET requests? Thanks in advance.

CRSF check is already skipped for GET request in rails
http://guides.rubyonrails.org/security.html
3.1 CSRF Countermeasures
— First, as is required by the W3C, use GET and POST appropriately. Secondly, a security token in non-GET requests will protect your application from CSRF.
You can see the method itself as well.
http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection.html#method-i-verify_authenticity_token
.... Also, GET requests are not protected as these should be idempotent. ....
verified_request?()
Returns true or false if a request is verified. Checks:
is it a GET request? Gets should be safe and idempotent

If you have cross domain application you could have errors with authtoken verifying and you can disable it, but of course your application won't be secure. In rails 3 there are special methods for cross domain solution in out of box

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

Why should spring postOnly be false for Logout to work?

what does postOnly mean in below property
grails.plugin.springsecurity.logout.postOnly=false?
Why should it be false for Logout to work? Tried making the logout feature work by making it true. But it did not work. What is the reason behind making it false?
For starters, please read the plugin documentation - the 2.x docs are here and the 3.x docs are here.
The plugin defaults to requiring a POST request to logout, but using the config setting you reference you can make your application more convenient to use but less secure by allowing GET or POST requests.
GET requests (e.g. regular links) are supposed to be for actions that read data. A strict REST API requires that GET requests be read-only and also idempotent, but obviously in a regular web app this is too strict. But in general it's best to use links and GET requests to request information, and POST/PUT/DELETE/etc. requests to make changes.
If you include a logout link that uses GET to make the request, it's possible for someone using XSS or similar attacks to trick your browser into logging you out. This isn't a severe vulnerability and requiring POST doesn't make it significantly harder for an attacker but it does raise the bar.
With the default configuration all you need to do is replace a logout link with a simple form that POSTs to that same url (and you can optionally use CSS to style the submit button like a link if you want). If you're comfortable with allowing users to logout with a GET request, change the setting to false and any request to that url will work.
Once you make it true as below
grails.plugin.springsecurity.logout.postOnly=true
the request method type should be POST only i.e. you can't use GET method.
So, change the logout call to POST type in this case.
You may also look at How to customize Grails Spring Security Core 2 login / logout controller and views?
By default Spring Security requires logout to use a POST request to provide CSRF protection. For more on CSRF see Wikipedia.
what does postOnly mean in below property
I means you grails will only logout a user if you send a POST request to the logout url.
Why should it be false for Logout to work?
It's mainly for CSRF protection.
It is considered best practice to use an HTTP POST on any action that
changes state (i.e. log out) to protect against CSRF attacks. If you
really want to use an HTTP GET, you can use logoutRequestMatcher(new
AntPathRequestMatcher(logoutUrl, "GET"));
Additionally, modern browsers like chrome will preload links in a page before the user tries to access them to make them fast. This means if you make your logout link accept GET requests, chrome might log you out even if you don't want to.

CSRF Token in Django and iOS

So I am trying to understand what to do here... I am doing a POST call to my Django server from iOS and I keep getting the 403 Error (Invalid CSRF Token). I am thinking about implementing a function that will return me the token (you will need to be logged in to access that function), and then add the token to my POST call.
Now... I don't understand what is the point of doing that? If I use TastyPie and the required login is APIKey... should I just exempt the csrf check?
To make sure I understand things right... is the CSRF generated per user session? Therefore, if I don't use Cookies, CSRF is not necessary?
How do people usually use their Django Servers with an iOS and making such POST calls?
Thanks!
You're right: if you don't use cookies to manage your sessions, you don't need CSRF protection. CSRF works because session cookies are automatically attached to the request; access tokens are not.
I personally found this article very useful. It is definitely worth reading, and would probably answer a lot of your questions.
As for tastypie: it allows SessionAuthentication. If you allow session authentication in tastypie, I suggest you look into a way to protect your users against CSRF. For other authentication schemes this doesn't seem necessary. As far as I know, Dmitry is right about tastypie disabling CSRF by default, which means it is strange that you get that 403 Error. Perhaps there is something else going on. Try wrapping the view in #csrf_exempt.
As for CSRF tokens, they are also called session independent nonces. They are meant to be permanent, but you probably know that is impossible for cookies. Anyway, this means that CSRF cookies persist through sessions.
You're right, CSRF does not make much sense in this case, because its purpose is to protect users from data tampering in a browser.
I believe that Tastypie disables CSRF on its views by default.

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.

CSRF protection and cross site form access

I aw working on cross site authentication (some domains have got common authentication). So I want to send authentication data (login, password) to main domain from others.
How should I use protect_from_forgery and how can I check if data received from valid domain?
What I am thinking now is to turn off protect_from_forgery for session controller and check domain name of received data.
But maybe I can configure CSRF protection for not only one domain?
The protection work with checking the session[:_csrf_token], so if you session is same in all of your domain, the protect_from_forgery can works.
What you are purposing is the very definition of a CSRF vulnerability. Forcing the user to Login or log-off generally isn't useful to the attacker. To pull off this hack the attacker would have to know the Username and Password, which defeats the purpose of "Session riding" on another user's authenticated session. As a hardcore hacker that writes CSRF exploits I'm telling you that this isn't a serious problem.
A easy way to patch this is to check the referer and make sure the login request is originating from a whitelist of domains. Another way to patch this is to use a Capthca like reCapthca. Yes you read that right. The reason why this works is because an attacker cannot solve the capthca with javascript or flash to "forge" a valid login request.

Resources