56

I understand the purpose of the Access-Control-Allow-Credentials header, but can't see what problem the Access-Control-Allow-Origin header solves.

More precisely, it's easy to see how, if cross-domain AJAX requests with credentials were permitted by default, or if some server were spitting out Access-Control-Allow-Credentials headers on every request, CSRF attacks would be made possible that could not otherwise be performed. The attack method in this scenario would be simple:

  1. Lure an unsuspecting user to my malicious page.
  2. JavaScript on my malicious page sends an AJAX request - with cookies - to some page of a target site.
  3. JavaScript on my malicious page parses the response to the AJAX request, and extracts the CSRF token from it.
  4. JavaScript on my malicious page uses any means - either AJAX or a traditional vessel for a CSRF request, like a form POST - to perform actions using the combination of the user's cookies and their stolen CSRF token.

However, what I can't see is what purpose is served by not allowing uncredentialed cross-domain AJAX requests without an Access-Control-Allow-Origin header. Suppose I were to create a browser that behaved as though every HTTP response it ever received contained

Access-Control-Allow-Origin: *

but still required an appropriate Access-Control-Allow-Credentials header before sending cookies with cross-domain AJAX requests.

Since CSRF tokens have to be tied to individual users (i.e. to individual session cookies), the response to an uncredentialed AJAX request would not expose any CSRF tokens. So what method of attack - if any - would the hypothetical browser described above be exposing its users to?

Mark Amery
  • 1,777
  • 2
  • 13
  • 19

2 Answers2

29

If I understand you correctly, you are saying why is the browser blocking access to a resource that can be freely obtained over the internet if cookies are not involved? Well consider this scenario:

www.evil.com - contains malicious script code looking to exploit CSRF vulnerabilites.

www.privatesite.com - this is your external site, but instead of locking it down using credentials, you have set it up to be cookieless and to only allow access from your home router's static IP.

mynas (192.168.1.1) - this is your home server, only accessible on your home wifi network. Since you are the only one that you allow to connect to your home wifi network, this server isn't protected by credentials and allows anonymous, cookieless access.

Both www.privatesite.com and mynas generate tokens in hidden form fields for protection against CSRF - but since you have disabled authentication these tokens are not tied to any user session.

Now if you accidentally visit www.evil.com this domain could be making requests to www.privatesite.com/turn_off_ip_lockdown passing the token obtained by the cross-domain request, or even to mynas/format_drive using the same method.

Unlikely I know, but I guess the standard is written to be as robust as possible and it doesn't make sense to remove Access-Control-Allow-Origin since it does add benefit in scenarios like this.

SilverlightFox
  • 33,408
  • 6
  • 67
  • 178
  • 14
    So, if I might summarize: a browser client could act as an intermediary to help a malicious server reach some destination resource `R`, normally accessible to only you. Normally, we consider the case where `R` is protected by a cookie-based auth token system, but you present a situation in which `R` is protected by network topology instead. The OP's imagined browser (which always assumes `A-C-A-O:*`) would violate network-topology-based protection. – apsillers Oct 18 '13 at 15:41
  • @apsillers Yes, that sums up my answer nicely. – SilverlightFox Oct 18 '13 at 15:50
  • 2
    There are also other services that use IP address ranges to restrict access (such as academic publishers which control access to content using university IP address ranges). If anonymous cross-domain requests were allowed everywhere, any web page could fetch and read that content if the client is within the range of allowed IP addresses. – Alf Eaton Jul 30 '14 at 13:19
  • 1
    You can read about [Clickjacking](https://www.owasp.org/index.php/Clickjacking) to understand a different possibility of exploitation. :) – Anonymous Platypus Dec 10 '15 at 07:01
14

What initially bothered me with CORS policies was their indiscriminate application regardless of resource/type, I feel that sentiment resonates with your question quite well. W3 spec actually advises that:

A resource that is publicly accessible, with no access control checks, can always safely return an Access-Control-Allow-Origin header whose value is "*"

So while the scenario in @SilverlightFox's answer is possible, IMHO it was unlikely to be considered when writing the spec. Instead, W3 appears to be driven by an "everything that isn't explicitly allowed should be restricted" mentality in this instance, which backfires when correct headers aren't set or support is lacking by individual browsers:

  • Rich client-side applications using third-party RESTful APIs where authentication, if any, is sent with every request so that there is no "session" to hijack (that's stateless for you!). Still, .json responses are subject to CORS so now you have to convince the third party to either implement jsonp, or a suitable Access-Control-Allow-Origin header, or give up and set up a tunnel to their endpoint (guess which one I'll be using).

  • Webfonts are subject to CORS, although afaik only Firefox implemented this draft spec. This means that if you're using a CDN for fonts (or a subdomain for all static content), it best be *-enabled!

  • Bonus herp derp points for CDNs which don't reply with an * header but echo the request Origin header value instead: if it gets cached on a proxy with an ...-Allow-Origin: domainA, your users from other domains will not be able to access it without cachebusting (which is kind of a setback in terms of CDN performance benefits).

  • There are also a few fringe scenarios like using external images/videos with canvas.

These inconveniences when accessing *-suitable resources could be simply considered acceptable since at least CORS is in play by default when it matters most.

Oleg
  • 240
  • 1
  • 4
  • 2
    2c -- most people (especially in the beginning) write sites assuming a user at a browser is using the service. They haven't considered the case that third party malicious site evil.com is probing his API. Returning a * sorta means you've considered this. Although not if you just set your server to respond with a *, and your particular site may not have considered this.. I still think the spec is cumbersome and seems too server centric. – Gerard ONeill Feb 16 '17 at 23:10
  • This is the correct answer. If I have a native app, I can make whatever cross-site cookie-less requests I want, but in the browser, that is not allowed. :( – David Barratt Aug 14 '18 at 12:46