This question is kind of a duplicate of: Why same origin policy for XMLHttpRequest
However, this answer isn't satisfactory because it doesn't address the fact that there are workarounds (as stated in the question). The answer only addresses security concerns related directly to the XMLHttpRequest but these problems are still present with JSONP (and possibly CORS, not sure). So the question still remains - Why have a strict Same Origin policy when there are workarounds like JSONP that's arguably even worse (because it's executable rather than static content)?
Here's an example:
Company.com wants to make an AJAX call to some unprotected resource, like a simple public API for some data lookup. Company.com realizes that this may be insecure so they will carefully scrub the data to ensure there is no funny business. However, XMLHttpRequest does not allow this, so Company.com must use JSONP, but this would prevent the scrubbing of data and could result in an Attacker injecting arbitrary Javascript onto the page. How is this a better solution?
Another example:
Company.com has a vulnerability and an attacker is able to inject Javascript onto the page which is then viewable by some user (there are a million ways this can happen; it's probably the most common website attack). With a strict Same-Origin policy, the attacker can mess with the page all day long but he can't "call home" which is an important detail because it means all your data is safe. But JSONP (and image tags) break this by allowing the attacker to scrape all your personal data from the page and send it wherever. This is still a reality even with CORS because I can tell my rogue server to allow inbound XS requests from any domain.
In other words, in what scenario does a locked-down XMLHttpRequest actually provide a greater degree of security?
Your premise is incorrect. The Same Origin Policy says nothing about the ability of a web page to include resources on an external domain. It prevents direct access to resources via scripting that are owned by different Origins without them opting in.
Therefore CORS and JSONP are not workarounds for the Same Origin Policy. CORS enables an Origin to opt in to XHR requests with responses, and JSONP is simply a hack to allow an external reference to return dynamic data to the page.
The point here is to secure your page so that XSS is not possible in the first place. To do this the focus should be on correctly encoding text that is output to the page. This will prevent 'phoning home' as an attack will not be possible in the first place. A Content Security Policy can help neutralise any script that manages to slip through the net. A regular security vulnerability assessment on your website should pickup unencoded output - think of the CSP as filling in the gaps between when these are found and fixed, although browser support is not fully there yet - especially with Internet Explorer.
However, XMLHttpRequest does not allow this, so Company.com must use JSONP, but this would prevent the scrubbing of data and could result in an Attacker injecting arbitrary Javascript onto the page. How is this a better solution?
It is not. CORS is a better solution as the request retrieves data rather than executable code. CORS allows XMLHttpRequest to do this.
With the CORS response header Access-Control-Allow-Origin
the website owner of example.com
could set this to
Access-Control-Allow-Origin: https://company.com
to allow only company.com
client-side access to the data over HTTPS via a user's browser.
In this CORS scenario, example.com
is trusting company.com
with the data response for that particular request only. In combination with the Access-Control-Allow-Credentials
header they can optionally request any authorisation cookies from the user at their browser be sent with the request, and the response to be read by JavaScript at company.com
.
In a JSONP scenario, company.com
would be trusting example.com
with their whole Origin. This means they are trusting example.com
with the whole client site security model. Example.com
could do anything it wants to company.com
's site. So if example.com
is compromised by hackers, they could also control company.com
user sessions once each user visits the page containing the <script src="https//example.com/
... tag.
In other words, in what scenario does a locked-down XMLHttpRequest actually provide a greater degree of security?
Everywhere on the internet.
Say you were logged into Gmail. For argument's sake, say Gmail had an AJAX method that got your inbox contents:
https://gmail.com/services/inbox/get_conversations
Now, you are surfing the web and you land on my site, evil.com
.
Evil.com
contains some JavaScript to make a POST request to https://gmail.com/services/inbox/get_conversations
, which will send your cookies from gmail.com
back to gmail.com
as you are logged in.
The service at https://gmail.com/services/inbox/get_conversations
will dutifully return the contents of your inbox.
Without the Same Origin Policy locking this down, evil.com
would be able to read the data in this response. i.e. any site could read your email. With the Same Origin Policy, the data is returned to the browser but no client-side script can read it apart from gmail.com
(and of course any other Origins allowed by CORS). For example, in this case Google might allow the following:
Access-Control-Allow-Origin: https://google.com
Note: All of the above is made up by me as an example for illustrative purposes and in no way reflects how Google and Gmail actually do this. In principle it will be the same.