When is it safe to enable CORS?

Jeroen picture Jeroen · Mar 15, 2012 · Viewed 38.5k times · Source

I am developing a JSON/REST web API, for which I specifically want third party websites to be able to call my service through AJAX. Hence, my service is sending the famous CORS header:

Access-Control-Allow-Origin: *

Which allows third party sites to call my service through AJAX. All fine so far.

However, a subsection of my web api is non-public and requires authentication (pretty standard stuff with OAuth and an access_token cookie). Is it safe to enable CORS on this part of my site as well?

On the one hand, it would be cool if third party websites could have ajax clients that also interact with this part of my service. However, the reason that there is a same origin policy in the first place, is that this might be risky. You don't want any website that you visit afterwards to be able to access your private content.

The scenario that I am afraid of is that a user logs in on my web api, either on the website or through a website that he trusts, and he forgets to logout. Will this allow every other website that he vists afterwards to access his private content using the existing session?

So my questions:

  • Is it ever safe to enable CORS on non-public content?
  • If a CORS enabled server sets a session_token through a cookie, will this cookie be saved under the domain of the CORS server or main web-page server?

Answer

monsur picture monsur · Mar 15, 2012

In answer to your second question (If a CORS enabled server sets a session_token through a cookie...?), the cookie is saved under the domain of the CORS server. The main web page's JS code can't access the cookie, even via document.cookie. The cookie is only sent to the server when the .withCredentials property is set, and even then, it is only accepted when the server sets the Access-Control-Allow-Credentials header.

Your first question is a little more open ended. It is fairly secure, but there are ways to circumvent things. For example, an attacker could use a DNS poisoning technique to cause a preflight request to hit the actual server, but send the actual CORS request to the rogue server. Here are some more resources on CORS security:

Lastly, your concern is around giving any website access to your CORS data. In order to protect against this, you should not use the Access-Control-Allow-Origin: * header. Instead, you should echo back the user's Origin value. For example:

Access-Control-Allow-Origin: http://www.example.com

This header will allow only http://www.example.com to access the response data.