[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: proposal: xsrf protection for restful web services



Hi, Chris,

On 02/20/2014 11:24 PM, Chris Travers wrote:
Right now, the current 1.4 web services don't provide a great deal of strong protection against xsrf. The current approach is not really safe enough, and so right now, unless we find a way to fix this, we'd need to recommend opening up that section of urls only to trusted hosts (i.e. servers). While this seems like a big limitation, if you restrict by client-side certificate you could allow access from dedicated non-browser mobile clients but not web browsers.

There is another option though, in that we could allow for some sort of digital signing of a component of a request. Unfortunately, this is going to require going with perl modules (which don't have a perfect cpantester record) or pgcrypto as an extension. However, you could have a public key, and you could check the signature of a specific set of information.

A third option would be a pre-shared auth key that would be submitted with every request, and tied to the user. The positive side is that it would be simple. The negative side is that the tokens would be long-term valuable and if compromised would provide a means to exploit xsrf via the browser if the user accounts are shared.

For now (1.4) I think recommending client-side certs would provide the most protection, but while this provides good protection for dedicated clients it means effectively locking browsers out of the restful web services.

Our current csrf protections for the web app, while better on the browser than any others that could be implemented there with RESTful principles, is certainly not RESTful, as it requires effectively pre-authorizing every write request (i.e. get the authorization token then add it to the post request). This requires a double-round trip to make a write effective.

Anyway, feedback is requested.


This is an area I was overdue for investigating ;-)

I found a bunch of useful links on preventing CSRF on REST APIs, and based on that, I think we should handle this a couple different ways.

First of all, if we're going to move more application management to the browser (for example, build an invoice with Javascript and post the result as JSON into the back end when done, which is a pattern Erik and I were discussing yesterday) we want to support having browsers use the RESTful web services. And of course, what use is an API if you can't use it from another service? So yes, we want something relatively simple to implement for both cases. A client-side certificate seems like a lot of extra work when writing a client, and not a common pattern.

So we need to cover two cases when authenticating a request: a request from a user logged into the web site, and a request from anywhere else.

We already use a session identifier for the web site, so we can detect if a user has recently logged in. To cover this case, I am thinking the "double-submit" pattern described here would be sufficient: http://appsandsecurity.blogspot.com/2012/01/stateless-csrf-protection.html (and make sure we don't require that for GET requests). That is, the client sends the same value in a Cookie as well as in the data of a POST, PUT, or DELETE request. That does not even need to be generated server side to prevent CSRF -- the server should just verify that for authenticated sessions, these values match.

For API calls that do not involve a session, we already require authentication. I think it's reasonable, if we require a session for authentication, for a web service client to either do a double-submit or a "synchronizer token" (which I think describes our current anti-CSRF protection) -- the client can route all requests through a central broker to apply the next token to the data before submitting.

Here's what I found useful:

http://appsandsecurity.blogspot.com/2012/01/stateless-csrf-protection.html
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet
https://www.owasp.org/index.php/REST_Security_Cheat_Sheet
http://security.stackexchange.com/questions/20187/oauth2-cross-site-request-forgery-and-state-parameter

The key thing for CSRF attacks is the attacker does not have access to the credentials themselves, or any cookie values. If we can detect all requests coming from our app and double-check against state that cannot be accessed from a different site, we block a CSRF attack. For any other API consumer, the app already needs to supply authentication.

Cheers,
John Locke
http://www.freelock.com


Cheers,
John Locke