Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass the CSRF token between rails applications

Our rails3 application talks to another rails application exposed as REST functions. We get the following warning post migration to rails3 on all POST calls made to the REST services.

WARNING: Can't verify CSRF token authenticity

How should we pass the csrf token on the wire when we make a POST call to the REST services, the ApplicationController has protect_from_forgery method and the call also lands on the handle_unverified_request call. We use HTTP basic auth to authenticate and it seems to work fine. What should we do to resolve this issue.

like image 447
Sam Avatar asked Feb 04 '12 13:02

Sam


Video Answer


1 Answers

Ok now I'll give it a shot to answer your question.

CSRF tokens are "session dependent" this means the user must share a session with the application he is communicating with. This means a request must have been made before he submits the actual form which is the case for standard HTML forms where the form is displayed before it is submitted so there's room to generate a CSRF token for this user.

Let's call the Application which serves the UI Button App1 and the one hosting the REST Service App2.

The User shares a session with App1 and gets the UI Button served by App1. Once the user clicks the button a request to App1 is made, and App1 makes a request to the REST Service of App2.

Conclusion: The user doesn't share a session with App2 but your App1 has a session with App2. This concludes in two things:

  1. The User is not vulnerable to Cross-Site-Forgery on App2 because he doesn't have a session on that server. So if I post a something like <img src="http://app2.com/rest-service/destroy> here, App2 wouldn't recognise me because I don't share a session with App2 and nothing happens.

  2. You can implement your own security measures on the REST Service to secure it from the public:

    • Authentication by HTTP Basic Auth
    • Authentication by an API Key
    • ....

This means you can drop the CSRF protection on the REST Service and stay on the safe side as long as user's can't make direct calls via AJAX etc.

Addition

CSRF protects your site from submitted forms that do not come from your origin (actually this applies to POSTed forms only since they usually manipulate data.

The big scenario is: I'm the attacker and I'd like to update your users account name to "Mr. Potatoe" the way I'd do that is to place a hidden form on my website which gets POSTed to Yourdomain.com/account with a hidden field like account[name]="Mr. Potatoe". Now what happens without CSRF protection? My browser submits the form, and sends the authentication cookie with it and my name is now "Mr. Potatoe". What happens with CSRF protection? My browsers submits the form and sends the cookie but the form has no CSRF token so the request gets rejected. Now is there a way as attacker to get the CSRF token under these circumstances? The answer is no. Maybe you ask yourself....

  • What if I place a hidden iframe on my site which points to Yourdomain.com/account/edit and just copy the hidden field containing the token? - Answer: It won't work because of same origin policy, you can't read whats inside an iframe if its content doesn't come from your domain.

  • What if I make an AJAX call in the background to get the token? Answer: It won't work because using pure AJAX you are bound to the same origin policy as well.

Now let's get to the point: I can't send a hidden AJAX call from my page to yours to harm your user who is on my site.

What does it mean? You can implement a before filter which checks if request.xhr? is true or whether the user agent is something like "My REST Client XY" because this can't be forged by a cross site request in a >>browser<<. So if this is the case you can ignore/disable the CSRF protection.

By the way if you want to make an AJAX request within your site you can get the CSRF token like this:

var token = $('meta[name="csrf-token"]').attr('content');

See the Rails UJS Script: https://github.com/rails/jquery-ujs/blob/master/src/rails.js#L81

NOTE: this only protects you from cross site forgery and nothing else....

like image 113
sled Avatar answered Sep 22 '22 09:09

sled