CORS Demystified!

Background

CORS stands for Cross Origin Resource Sharing. This is security feature supported by Browsers that allows the UI applications to be hosted on a separate domain from the underlying APIs that are used. This is what enables the API Economy work! The consuming applications can call APIs hosted on different domains from different providers to build meaningful applications to the end user. If the UI and API were to be hosted on the same domain, this makes the applications very restrictive in the functionality they can provide as they can only call services that are hosted on the same domain!

Lets talk about how this all started! Long time ago when Dinosaurs were roaming the earth, yeah not so long, but you get the point, browsers allowed AJAX calls only to the domain where the page was loaded from. Let us say that the page was loaded from http://www.xyz.com, the browser would allow AJAX calls back to http://www.xyz.com. The reason they did that was to protect the end user from below scenario.

  1. User logs on to http://www.xyz.com and gets authentication cookie. Let’s call it xyzauthtoken cookie that is scoped to the domain xyz.com
  2. Now the user while logged on to xyz.com navigates to another site, http://www.evil.com
  3. evil.com generates an AJAX request to xyz.com. Browser sends the xyzauthtoken cookie along with the request allowing evil.com to impersonate the user logged in to xyz.com. This is pretty bad!

However as web applications evolved, this security feature made it very restrictive for applications from consuming services/APIs from different providers that are hosted on different domains.

CORS spec was put-together by major Browser providers to solve this problem. Chorme, Safari, Firefox were the early adopters of this security feature where as IE started supporting CORS only from IE version 10 and above!

How does CORS work?

CORS empowers the API providers and allows them to control who can consume their services over AJAX. The below diagram depicts the CORS flow!

  1. User logs on to http://www.xyz.com and gets authentication cookie. Let’s call it xyzauthtoken cookie that is scoped to the domain xyz.com
  2. Let us say, the webapp invokes services hosted on api.123.com to get some data. The user has to authenticate to api.123.com, but that is beyond the scope of this article! Just in case you are curious, OAuth solves that problem, a topic for future blog post!
  3. The CORS supported browser, holds the request and issues something called a pre-flight OPTIONS request to api.123.com with a request header set to Origin=www.xyz.com. The browser does not send any cookies with the preflight request.
  4. Now api.123.com can decide weather to accept a request from xyz.com. If api.123.com is okay serving up a request from xyz.com, it responds with response header, Access-Control-Allow-Origin, that specifies all the domains that can access api.123.com. The header can take regular expressions and if api.123.com can accept requests from any domain, you can set something like Access-Control-Allow-Origin=*.
  5. The browser checks if the value in Access-Control-Allow-Origin matches to the value in Origin. If there is a match, the browser releases the original request to api.123.com
  6. The AJAX request to api.123.com is sent and the app is able to get the data from a service hosted on a different domain!

How does CORS protect the end user?

In the above scenario, lets say api.123.com allows AJAX only from xyz.com and abc.com. The service could have set Access-Control-Allow-Origin header as follows:

Access-Control-Allow-Origin=xyz.com,abc.com

Now, imagine a scenario where the user navigates to http://www.evil.com and the malicious site issues a AJAX request to api.123.com. Let us see how CORS protects the user from this call.

  1. The CORS supported browser, holds the request and issues a pre-flight OPTIONS request to api.123.com with a request header set to Origin=www.evil.com. The browser does not send any cookies with the preflight request.
  2. api.123.com responds with Access-Control-Allow-Origin=xyz.com,abc.com
  3. The browser checks if the value in Access-Control-Allow-Origin matches to the value in Origin. In this case, it does not match and the Browser drops the request and no call is made to api.123.com

CORS spec allows the Provider of any API to specify what Http Methods and Http Headers can be sent by the Consumers and provides flexibility in accepting lets say a GET request from any domain and restrict a PUT/POST to only a sub-set of trusted domains.  If you need more information on CORS and all the features supported by CORS, it is well documented here!

Next time you are Banking or checking your investments online, turn on Developer Tools (F12) in your browser and see how the AJAX calls are being handled!

Advertisements

Author: appsecfordevs

I am an Application Security professional helping organizations secure their Applications, and Data from internal and external threats. I have expertise in Application Architecture & Development, providing me the insights in to developing controls to defend applications against security vulnerabilities. Disclaimer: The opinions expressed here are my personal opinions and do not reflect those of my current or former employers and clients!

One thought on “CORS Demystified!”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s