10 September, 2014

CORS Global Policy

CORS Global Policy
Jason Gillam
Author: Jason Gillam

I recently noticed an uptake on Cross-Origin Resource Sharing (CORS) findings showing up in automated scanning tools, which would not have been a significant concern except for the fact that the tools were rating this as a relatively “high” severity and very few people I asked about it seemed to have any idea what it was. I love to find obscure quirky behaviors that can be turned into vulnerabilities… but first we need to determine whether or not it is as bad as the scanning tools lead us to believe.

So what is CORS?

Simply put: it’s a mechanism that creates a contract between a browser and a server permitting an exception to the Same Origin Policy. This is an extremely important aspect of today’s application mashup dance party where all sorts of applications are intentionally interacting with each other in dynamic ways which must work around the Same Origin Policy. It is accomplished through request and response headers in such a way that the browser will identify all script-based requests with an Origin header, to which the server will respond with a set of cross-origin restrictions. The browser will only proceed with sending requests that adhere to the restrictions. The whole thing is slightly more complicated than this so if you want more details I recommend giving this a read: http://www.html5rocks.com/en/tutorials/cors/

Now the really interesting part of this from a penetration tester perspective is when we start involving cookies. It is possible to use CORS in what is known as a “with Credentials” mode, which will in fact send cookies during a cross-origin request. By this I mean that if you establish a session cookie with one origin, that cookie will be sent during any CORS requests (from other origins) to that origin. This allows a cross-origin request (e.g. an AJAX call) from one site to interact with another site as if the user was logged in.

So here is the line the scanning tools complain about:

Access-Control-Allow-Origin: *

…and I see why. With a global wildcard policy like this (on any site containing sensitive data), wouldn’t that mean a user browsing any attacker-controlled site is at risk of a cross-origin call pulling data off the target site? Researching this did not yield a satisfactory answer so I decided to write some test code and experiment with some scenarios on a few different browsers to see how they reacted. I tested Firefox 31.0, Chrome 37.0, and Safari 7.0.6 and all three of these yielded the same results.

What’s the Risk?

In answer to the risk question: cross-origin requests using the “with Credentials” mode appear to fail if a global wildcard origin policy (i.e. Access-Control-Allow-Origin: *) is set. Such requests do not fail if specific origins are listed. So is there really a risk here or are the scanning tools overreacting?  As is often the case, the answer isn’t as simple as “yes” or “no”.  While experimenting with CORS and looking at some of the server configurations out there I realized that a typical server solution consists of simply adding CORS response headers.  They do not automatically perform filtering based on the values of these headers.  That is a job left up to applications and the browser.  In the case of the browsers I tested it seems like the browser is doing its job by not accepting the response body for requests against the server’s CORS restrictions.  But the server is still sending the response body.  So if you examine CORS communication through a intercepting proxy (e.g. Burp), you will see that even though your Javascript can’t read the CORS response, it is still sent over the wire unless the application is smart enough to respond based on Origin headers.

So what does this mean for penetration testers?  I feel we have not yet reached the end of the story.  So far my testing suggests that it is not common practice (yet) for servers to filter response based on Origin headers.  At a minimum this means the responses of an overly-permissive CORS policy can be easily captured by a proxy.  So an overly-permissive CORS policy combined with lack of Origin filtering and cleartext (HTTP) communication sounds to me like a solid recipe for data theft.

Next steps

I would like to see if a CORS request can be sent through a Javascript-based proxy within the same context.  In addition a lot more testing needs to be done on how different web servers handle Origin filtering.

Want to talk about it?

I will be teaching a Web Penetration Testing course at  AppSec USA next week and would be happy to discuss this research.

Jason Gillam is a Senior Security Consultant with Secure Ideas. If you are in need of a penetration test or other security consulting services you can contact him at jgillam@secureideas.com, on Twitter @JGillam, or visit the Secure Ideas – ProfessionallyEvil site for services provided.

Join the professionally evil newsletter

Related Resources