[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: proposal: xsrf protection for restful web services
- Subject: Re: proposal: xsrf protection for restful web services
- From: John Locke <..hidden..>
- Date: Fri, 21 Feb 2014 08:21:20 -0800
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
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
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
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:
(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:
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.