2

As I understand it, with CORS, on cross-origin requests, the browser will send an Origin header, and if the origin isn't allowed, the server will still send back a 200 response with a non-matching Access-Control-Allow-Origin header (or a response that simply lacks that header), and leaves it to the web browser to block the response from the page.

My question is, why wouldn't the server be responsible for detecting the non-allowed origin and return a 403 response instead? Wouldn't you want to block the content from being provided further upstream?

As an example,

var xhr = new XMLHttpRequest() ; 
xhr.open( 'GET' , 'https://www.bing.com' ) ; 
xhr.send() ;

enter image description here

enter image description here

1

Backwards-compatibility.

Back in the days before it was possible to send HTTP requests from JavaScript there was no need for web servers to check what site a request "originated" from, so they didn't. When JavaScript did get this ability, it had to be implemented in a way that wouldn't break the security of existing websites. Therefore, browsers took on the responsibility of making sure that data from one website couldn't be accessed by a different site. (Cross-origin AJAX requests would simply not work.)

Later it was decided that this policy was too restrictive, and thus the Cross-Origin Resource Sharing (CORS) standard was created. Once again, this standard had to be backwards-compatible with existing servers, and those servers still didn't check the Origin header. Why would they? Browsers already prevented cross-origin access to site data automatically; there was no need for a separate check. Therefore, CORS had to require sites to explicitly opt-in to cross-origin access to a specific page. Requiring an opt-out (via rejecting the request if the Origin header is wrong) would, again, break the security of existing sites. Thus, the Access-Control-Allow-Origin header was born.

Even aside from backwards-compatibility though, there's still a significant benefit to not requiring servers to check the Origin header. Making cross-origin access require an opt-in ensures that developers and web servers don't accidentally compromise their own security by failing to properly validate the Origin header. It's secure-by-default rather than "insecure unless you make sure this particular header is set to the right value".

2

CORS does not work like you describe. It does not transfer data to the client which can not be transferred without Javascript. Every request which can not be achieved without Javascript is subject to the policy and the browser will check the CORS policy before doing such requests. In detail:

  • For simple requests any cross origin access is allowed. Simple requests are the ones which could also be triggered without Javascript by including image cross-site, submitting a form etc, i.e. these are XHR requests without special headers or methods.
  • For any other requests (like XHR with custom header, methods different from GET, HEAD and POST) a preflight request is done to get the CORS policy from the server. And only if this policy would allow the intended requests it is actually executed.

For more details see Mozilla: Cross-Origin Resource Sharing (CORS).

Sure, one might argue that a modified browser might simply ignore the CORS policy and request the content anyway. But, a modified browser might also send a faked Origin header to trick the server into providing the data. In other words: CORS is not a replacement for authentication. It is instead intended to allow cross-site requests using Javascript without adding additional vectors for CSRF attacks. Before CORS cross-site Javascript XHR was forbidden and insecure ways like JSONP were used.

  • Just because there is no preflighting for GET requests doesn't mean that they are allowed. – martin Apr 13 '18 at 11:55
  • @martin: Since you don't need to use Javascript to trigger the request in your edited question (a <form action=... would do it too) it counts as a simple request and thus is allowed. Again, CORS is not a replacement for authentication but is only to allow cross-site requests using Javascript without adding additional CSRF problems. – Steffen Ullrich Apr 13 '18 at 12:05

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.