I have an existing rails backend website which makes json calls to server. Now,I am developing a mobile iOS app to use the same backend and send calls in json. However, mobile requests are failing with:
WARNING: Can't verify CSRF token authenticity
Searching around stackoverflow, many suggested to disable csrf checks for json calls by using something like this:
# Or this in your application_controller.rb
def verified_request?
if request.content_type == "application/json"
true
else
super()
end
end
But my question is , I dont understand how does this prevent csrf attacks in json format? Attacker can always send a json request to our endpoint from their site. Anyone has insights into this? I couldn't find any clear answer to this.
Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.
Using a per-request csrf token (unique, random and unpredictable for each request) that be assign together with the session id in the cookie header is necessary for every GET request and both should be validate accordingly in the server side.
If you put your JWTs in a header, you don't need to worry about CSRF. You do need to worry about XSS, however. If someone can abuse XSS to steal your JWT, this person is able to impersonate you.
A CSRF token is a secure random token (e.g., synchronizer token or challenge token) that is used to prevent CSRF attacks. The token needs to be unique per user session and should be of large random value to make it difficult to guess. A CSRF secure application assigns a unique CSRF token for every user session.
What you are describing is very easy to exploit using Flash:
var request:URLRequest = new URLRequest("http://stackoverflow.com");
request.requestHeaders.push(new URLRequestHeader('Content-Type', 'application/json'));
request.data = unescape('{"a":1,"b":{"c":3}}');
request.method = URLRequestMethod.POST;
navigateToURL(request, '_blank');
If you look at the CSRF prevention cheat sheet you can check the referer to make sure its from a domain you trust. If the referer is blank then it could be originating from a https url, so that should be considered a failure. Relying on Ruby's CSRF token is a stronger form a CSRF protection.
This is a fix for ajax
Get csrf_token from rails or if using something else, from meta
// js file
var csrf_token = $('meta[name=csrf-token]').attr('content');
or
//js.erb file
var csrf_token = "<%= request.session["<%= _csrf_token %>"] %>";
then add this to js
$("body").bind("ajaxSend", function(elm, xhr, s){
if (s.type == "POST") {
// place lines mentioned above here
// line goes here...
xhr.setRequestHeader('X-CSRF-Token', csrf_token);
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With