How does same origin policy (SOP) work? - javascript

I had a read of what same origin policy means on Wikipedia however fail to understand how it works. I do understand that it prevents for example a javascript on my website from interacting with a script on a separate site however what does this exactly mean?

If your script (JS) tries to perform some HTTP request to the site other than the one it originated from via XMLHttpRequest, the request will fail, return status code will be 0 and error message - null.
That's how it worked originally.
Right now there is a Cross-Origin Resource Sharing (CORS) specification, which is more or less supported by most modern browsers. It allows to do such requests, but with strict limitations.

it means if you load
http://www.stackoverflow.com/
and your browser loads javascript, then that javascript cannot access a url that doesn't come from that page. There are a lot of details, for example, you could not access
https://www.stackoverflow.com
but an ajax request could access
http://www.stackoverflow.com/something/something
The browser itself would not allow the request to be fired.
EDIT -- This might be helfpul: http://www.google.com/support/forum/p/Chrome/thread?tid=171316324d16747b&hl=en

Related

What is the difference between get requests via XMLHttpRequest, curl, and browser URL in terms of CORS?

I'm trying to wrap my head around CORS (cross origin resource sharing) by reading https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS. Here, I noticed that the document states:
Cross-site HTTP requests initiated from within scripts have been subject to well-known restrictions, for well-understood security reasons. For example HTTP Requests made using the XMLHttpRequest object were subject to the same-origin policy.
This makes sense to me, as I have experienced the following error before:
XMLHttpRequest cannot load http://localhost:7000. No
'Access-Control-Allow-Origin' header is present on the requested
resource. Origin http://localhost:9000 is therefore not allowed
access.
However, why does curl http://localhost:7000 return the JSON that located on the page correctly? Is it simply the fact that curl commands don't come from scripts? In addition, how does the browser even recognize that the request is coming from a script? If this differentiates significantly from browser to browser, I'd be curious to know about how Chrome and Firefox detect this.
In my idea
XMLHttpRequest is javascript call server to get data and noad reload page. No page load first no XMLHttpRequest.
Curl is php server function get data from server and return to php code, curl is a part of server code.

Why Ajax GET request without CORS is blocked, but JSONP is allowed?

We can simply call GET request for any page on the web using html tags from another origin:
<script src="http://example.com/user/post?txt=sample"></script>
XHR other origin is blocked because of security reason, as an instance, attacker can post behalf of a user using GET request(Consider the fact that it is not possible because of lack of cookies). However, the above script tag will do the same(Same, cookies are not available). So why XHR GET request is not allowed?
GET requests are not supposed to change anything on the server. From RFC 2616 section 9.1.1:
In particular, the convention has been established that the GET and HEAD methods SHOULD NOT have the significance of taking an action other than retrieval. These methods ought to be considered "safe".
In your example of posting to a site using a GET request, the site shouldn't even allow that, and the same-origin policy isn't really meant to prevent it.
The reason XHR is treated differently is that XHR returns the HTTP response to the JavaScript code that made the request, so it has the potential to leak information. For example, if cross-domain XHR GET requests were allowed, a malicious script could query your bank's website to find out how much money is in your account.
Other methods of performing GET requests don't leak information. In particular:
You can add a <script> tag to the document, but the browser will try to run the response as a script. Unless the response is a valid script that's specifically designed to provide data using the JSONP convention, your code can't "see" anything that was in the response.
You can add an <img> tag to the document and maybe load some of the user's personal photos from another site, but the image will only appear on the screen; you can't access the pixel data from JavaScript.

Cross domain AJAX requests are not being blocked: is this a security vulnerability?

I spent the last 3 days studying how to make a cross domain request using XMLHttpRequest. The best alternative is indeed with JSONP which I am already using.
But I still have a question that I could not find answer nowhere. I read hundreds of posts (including SOs) and nobody has a good liable answer (with nice reference). Hope someone here can help.
Said that, I read in many websites that due to security reasons I cannot make an Ajax request from domain example.com to yyy.com and get the data I want. It's very clear and I have no question about that. BUT the problem is when I run the code below in my localhost (so my domain is "localhost" and I should not me able to request any data from another domain).
xhReq = new XMLHttpRequest();
xhReq.open("GET","http://domain.com.br?parameter",true);
xhReq.send(null);
When I inspect the Firebug Net Tab I realize that the request was not blocked! It was clearly requested. I could not believe. So I created a file in the domain.com.br/log.php where I could log any request that hit my domain. Surprisingly all the requests I was firing localhost were hitting my domain.com.br. When I tried to fetch the response I really could not get it due the same origin policy of my Chrome and FIrebug browser. But I was reallyl surprised that the request really hit the webserver despite I could no manipulate the responde.
More surprisingly is that if domain.com.br/log.php generates a huge responde with like 1MB my firebug showed me that the browser does download ALL th 1MB from the webserver, and at the end it shows a message "Access denied" as expected. So why download all the file if the same origin policy forbids that data to be read.
Finally, I makes me amazed, is that all the websites and specifications I read says very CLEAR that the request is blocked using Ajax when the target domain does not match the source domain. But clearly, with my experiment, the requests are being completed, despite I cannot have access to the response data.
What makes me upset is that it could be open a BIG security hole, in which a website with thousands of views everyday could run this 3 line code and cause a HUGE Ddos attack in an unfriendly website just making the users request a page in another website in small intervals since the browser will not block the request.
I tested this script in IE 7, 8 and 9 and Chrome latest and Firefox latest and the behaviour is the same: the request is done and the browser downloads all the response while not making it avaiblable to do SOP.
Hope someone can explain me why the specs are so wrong about it or what I am understanding wrong!
The request can be made, and the server may generate a response, regardless of CORS. However, the response may be hidden. balpha wrote about this in his blog recently:
Note that the same origin policy doesn't necessarily prevent the request per se – it just prevents the response from being accessible. A malicious site can e.g. just redirect your browser, or submit a form, or include an image or an iframe – in all those cases a request is made to your site; the evil site just doesn't see the response.
To some extent, the browser has to make a request to the server to see if it servers an "Access-Control-Allow-Origin" header. Remember that CORS is completely implemented by the browser. Someone could just write a console application to make a request to your server, so you shouldn't rely on CORS to make sure requests are only coming from your own site.
You can achieve the same effect (like a dos attack you said) with a simple image file, it does not necessarily need to be XHR. Link an image file from a different website, put millions of it in your page, display it to your users and boom.

Making AJAX calls from inside of an iframe with different domain

Is it possible to do AJAX calls from inside an iframe that has a different domain source?
I've tried script injection but it doesn't work because the iframe's source is secure.
I made a simple fiddle with California DMV website here.
I'm getting DOM exception 8 error. Is it a security issue?
It is not possible to modify or make JS calls in an iframe with a different domain source. This is restricted in all browsers for security reasons.
See the "Same Origin Policy" for a description of how inter frame security works. In a nutshell, there is very little communication allowed between frames on a different domain for security reasons. You cannot make any direct Javascript calls between frames on different domains.
There is a way to make cross domain ajax calls and it involves using JSONP. Basically, you inject a script tag into your own frame and that script tag points to server endpoint anywhere on the web. Since the src value of a script tag is not restricted by the same origin policy, you can reach that server. But, now you need to have a way to get that result back. That is done using JSONP where you specify in your server request a javascript function that you want the returned javascript to call. That returned javascript can have javascript data in it that is then passed to the desired function. JSONP requires cooperation between both client code and the server code since a normal ajax call might not support the extra part of JSONP. But, with this cooperation of both sides, you can get around the same origin policy for server endpoints that support JSONP.
HTML5 has a new messaging system that can safely communicate data (not direct JS calls) between cooperating frames in different domains. See here and here for a description of how the HTML5 messaging works.
Yes it's a security issue because of the Same Origin Policy enforced by most browsers: http://en.wikipedia.org/wiki/Same_origin_policy .
You can look into JSONP http://niryariv.wordpress.com/2009/05/05/jsonp-quickly/ which is specifically designed to get around this.

Cross-site ajax call to a WCF Service

Is it possible to do a cross-site call, in Javascript, to a WCF service?
I don't mind if it's a POST or a GET.
But I've heard that these days, browsers don't allow cross-site calls with either POST or GET.
How can I circumvent this and still call a WCF Service?
There's not a whole lot you can do to circumvent the browser's cross-site scripting blockers. Those blockers stop XMLHTTPRequest's from happening to any domain but the one that loaded the containing script or page.
That said, there is one commonly used workaround: Use JavaScript to write a new entry into the DOM that references a src that is a cross-site URL. You'll pass all your RPC method arguments to this "script" which will return some JavaScript that will be executed, telling you success or failure.
There's no way to do a POST in this manner, the src URL must be a GET, so you can pass arguments that way. I'm not sure if WCF has a "GET only" method of access. And, since the browser will expect the result of the remote tag to be a valid JavaScript object, you'll have to make sure that your WCF service obeys that as well, otherwise you'll get JavaScript errors.
Another common method of circumventing cross-site scripting is to write a proxy for your requests. In other words, if you want to access domain test.com from scripts hosted on example.com, then make some URL on example.com that proxies the request over to test.com in the proper way.
For your example, the proxying is likely the right answer, assuming that WCF doesn't have it's own cross-site scripting restrictions.
Are you using jQuery by any chance? jQuery supports Cross-Domain JSON requests using "JSONP". You will be limited to GET requests, but I've tried it out and it works well! It's also very simple to get working.
See the "Cross-Domain getJSON (using JSONP) " section on this page for details:
http://docs.jquery.com/Release:jQuery_1.2/Ajax
And here's some background on JSONP:
http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/
Let me know how it goes!
New W3C recommendations are being standardised to allow cross-site requests between trusted parties via the Access Control for Cross-Site Requests specification.
This requires a server serving suitable Access Control HTTP headers and a browser capable of understanding and acting upon such headers.
In short, if a remote host says it likes your domain, and a browser understands what this means, you can perform xmlHttpRequests against that host regardless of the same origin policy.
Currently very few browsers support this functionality. IE8 apparently does (I haven't tested it) and Firefox 3.1 does (I have tested this extensively). I expect other browsers to follow suit quite quickly.
You shouldn't expect sufficient adoption of compatible browsers until 2012 at the earliest.
That's the ultimate solution to the problem. The downside is waiting a few years before it can be used in mainstream applications.
If this is for use within an environment you fully control, such as for an intranet where you can determine which browser is used and where you can configure multiple servers to issue the correct headers, it works perfectly.
To expand on Ben's answer... I extended our WCF service to support JSONP calls from jQuery using code similar to this example from Microsoft:
http://msdn.microsoft.com/en-us/library/cc716898.aspx

Categories

Resources