1

I was in the middle of implementing a CSRF protection mechanism for my server when I realized that this attack only really affects web browsers. It got me wondering: why should I bother generating/validating CSRF tokens for non-browser clients?

Not only would removing such checks simplify the implementation of REST clients, it would also improve scalability.

I was thinking of having all HTML resources set a browserId cookie containing a cryptographically-strong pseudorandom value which identifies the client as a browser. Any calls into the REST api would check for this cookie and, if present, apply CSRF validation. Otherwise, the checks would be skipped.

The value of the cookie is not as important as its existence. The value is not stored or validated by the server, but it is useful for tying CSRF tokens to a specific browser (this prevents an attacker from passing his own CSRF token to a victim).

My question is as follows:

  • Is it possible to differentiate between machine-to-machine (M2M) and human-to-machine (H2M) clients? If so, what is the best way (is the above approach reasonable)?
  • Is it safe to differentiate between M2M and H2M clients, even if we can? Or does this open us up to possible attacks in the future?
  • Can an attacker delete cookies, assuming that I control all sub-domains and use HTTPS?
  • How do your non-browser clients authenticate? – David Jun 27 '14 at 17:45
  • @David, they pass their plain-text credentials to POST /authentications over HTTPS and I respond with an authentication id. They include that authentication id for future requests that require authentication. – Gili Jun 27 '14 at 18:08
2

CSRF is for forms mostly and it is not used for REST APIs at all. When REST API is implemented with API keys and nonce, you could say that these 2 act as your cross-site request forgery protection.

Also, when designing REST API it's usually best to avoid such things as cookies at all. Use per-user API Keys, this will also solve your identification problems.

Is it possible to differentiate between machine-to-machine (M2M) and human-to-machine (H2M) clients? If so, what is the best way (is the above approach reasonable)?

For a rest API it should NOT matter if the client is a machine or a human. To identify humans, use per-human API key which should be supplied upon every request. There is no such thing as machine or human (i.e. there is no difference). Everyone is a client for the API.

Is it safe to differentiate between M2M and H2M clients, even if we can? Or does this open us up to possible attacks in the future?

Answered above (you should not need to do this).

Can an attacker delete cookies, assuming that I control all sub-domains and use HTTPS?

Answered above (you should not use cookies for REST APIs).

  • How does this protect browsers from CSRF attacks? I assume I'd have one API key for the HTML page that uses the REST api under the hood (as opposed to one key per end-user of that HTML page)? How then do you protect end-user browsers from CSRF attacks? – Gili Jun 27 '14 at 8:50
  • 1
    You mean browsers that use the site which is based on REST API? Then you would use the usual CSRF measures for the website's forms themselves. This is not in the API itself, but on the webpage forms, which is a different thing. – user43488 Jun 27 '14 at 9:01
  • 1
    Yes, that is what I meant. CSRF checks must be enforced on the server side, so when you say you would use the usual CSRF measures for the website forms themselves what exactly do you mean? The forms trigger AJAX calls to the REST api, so how can you handle CSRF checks anywhere but in the server-side implementation of the REST api? – Gili Jun 27 '14 at 9:18
  • 1
    You would have CSRF in the form itself, which would be unique per client. If the CSRF does not match, the form should not reach the AJAX call part or it shouldn't be even generated. This is too much to answer in comments and is another question itself. – user43488 Jun 27 '14 at 20:53
  • This is a critical component of the question. Are you implying a client-side CSRF validation mechanism without any sort of server-side checks? – Gili Jun 27 '14 at 21:45
-1

Answering my own question.

Yes, I believe it is possible and safe to differentiate between browsers and non-browsers using the presence of cookies if and only if:

  • The attacker cannot read cookie values (guaranteed by SOP)
  • The cookie values are mandatory (preventing the attacker from making requests without them).

I propose splitting the server-side implementation into two:

  1. A core API for RESTful clients.
  2. A browser API that acts as a bridge for browsers.

  • The core API does not implement any browser-specific features (e.g. cookies, CSRF checks).
  • The browser API mirrors the core API (exporting equivalent, browser-specific, methods where necessary).
    • It is a server-side implementation that runs browser-specific security checks, and converts browser-specific features to the format expected by the core API (e.g. cookies to JSON values).
    • It forwards requests to the core API and converts the response back to a browser-specific format (creating cookies as necessary).

An attacker cannot bypass security checks by accessing the core API because it ignores cookies. Without cookies, an attacker cannot carry out CSRF attacks.

  • I am not sure why you repost same thing I have posted. The only difference is that you for some reason call your website "a browser (mirroring) API". – user43488 Jun 27 '14 at 20:23
  • @edvinas.me: Your answer was/is vague. I asked for a clarification but didn't receive a reply for over 12 hours so I developed the above system. If you meant the same thing, that's great, but I'm still under the impression that you're talking about something else (client-side CSRF validation). My answer spells out all the implementation steps in detail. – Gili Jun 27 '14 at 21:40
  • The question and implementation steps you have provided are as obscure and as vague and use some invented terms that only you are familiar with. I don't believe it is possible that you could've got any other answer really. You also seem to first answer that "it is possible and safe to differentiate between browsers and non-browsers using the presence of cookie", but then suggest to implement 2 different APIs, which is not really a differentiation method, just spliting the systems in separate parts. API part should be separate in the first place. – user43488 Jun 28 '14 at 9:49
  • In most of the questions you asked, you end up providing an answer yourself. A better approach would be to provide whatever steps you think are the best in your original question and ask the community to vet it's security. – void_in Jun 28 '14 at 19:28
  • @void_in, do you mean I should post a new (follow-up) question containing the steps in this answer and ask the community to vet it's security? – Gili Jun 29 '14 at 19:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.