Browser XSS: am I missing something? - javascript

I feel like I am missing something fundamental about XSS prevention (either in general or about the browsers' current implementation of it).
I have a site at domain A, that uses jQuery. Under certain conditions I want it to periodically retrieve and format some data which is hosted at domain B.
In the source for domain A's page, it appears that I can quite happily put in a <script src="http://B/something.js"></script> and it will load and execute the script in the context of the current page (in particular allowing it to read and update the DOM). I can also do the same thing using jQuery.getScript (which internally fetches and executes the script via AJAX).
However regardless of whether I put it into the domain A page or into the JS on domain B, if I try to use jQuery.ajax to load http://B/data.json it generates a CORS violation error:
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.
(Note that while testing this, domain A is a local file://, which is probably why it's showing a null origin there. It will be a "real" site in practice.)
I am having a hard time understanding this behaviour. I fail to see how loading JSON data is in any way less safe than loading arbitrary script -- in fact the opposite seems more likely.
Mostly I'm asking this question to try to understand how this can possibly make sense, but as a side question I'm interested to know the "right" way to perform this sort of thing (have a script on domain B be able to load data from its own domain, despite being run from domain A). It is possible for me to add the Allow-Origin header to domain B if absolutely required, but I would prefer not to do so. (It's not possible to do this on domain A.)

Related

Prevent local PHP/HTML files preview from executing javascript on server

I have some HTML/PHP pages that include javascript calls.
Those calls points on JS/PHP methods included into a library (PIWIK) stored onto a distant server.
They are triggered using an http://www.domainname.com/ prefix to point the correct files.
I cannot modify the source code of the library.
When my own HTML/PHP pages are locally previewed within a browser, I mean using a c:\xxxx kind path, not a localhost://xxxx one, the distant script are called and do their process.
I don't want this to happen, only allowing those scripts to execute if they are called from a www.domainname.com page.
Can you help me to secure this ?
One can for sure directly bypass this security modifying the web pages on-the-fly with some browser add-on while browsing the real web site, but it's a little bit harder to achieve.
I've opened an issue onto the PIWIK issue tracker, but I would like to secure and protect my web site and the according statistics as soon as possible from this issue, waiting for a further Piwik update.
EDIT
The process I'd like to put in place would be :
Someone opens a page from anywhere than www.domainname.com
> this page calls a JS method on a distant server (or not, may be copied locally),
> this script calls a php script on the distant server
> the PHP script says "hey, from where damn do yo call me, go to hell !". Or the PHP script just do not execute....
I've tried to play with .htaccess for that, but as any JS script must be on a client, it blocks also the legitimate calls from www.domainname.com
Untested, but I think you can use php_sapi_name() or the PHP_SAPI constant to detect the interface PHP is using, and do logic accordingly.
Not wanting to sound cheeky, but your situation sounds rather scary and I would advise searching for some PHP configuration best practices regarding security ;)
Edit after the question has been amended twice:
Now the problem is more clear. But you will struggle to secure this if the JavaScript and PHP are not on the same server.
If they are not on the same server, you will be reliant on HTTP headers (like the Referer or Origin header) which are fakeable.
But PIWIK already tracks the referer ("Piwik uses first-party cookies to keep track some information (number of visits, original referrer, and unique visitor ID)" so you can discount hits from invalid referrers.
If that is not enough, the standard way of being sure that the request to a web service comes from a verified source is to use a standard Cross-Site Request Forgery prevention technique -- a CSRF "token", sometimes also called "crumb" or "nonce", and as this is analytics software I would be surprised if PIWIK does not do this already, if it is possible with their architecture. I would ask them.
Most web frameworks these days have CSRF token generators & API's you should be able to make use of, it's not hard to make your own, but if you cannot amend the JS you will have problems passing the token around. Again PIWIK JS API may have methods for passing session ID's & similar data around.
Original answer
This can be accomplished with a Content Security Policy to restrict the domains that scripts can be called from:
CSP defines the Content-Security-Policy HTTP header that allows you to create a whitelist of sources of trusted content, and instructs the browser to only execute or render resources from those sources.
Therefore, you can set the script policy to self to only allow scripts from your current domain (the filing system) to be executed. Any remote ones will not be allowed.
Normally this would only be available from a source where you get set HTTP headers, but as you are running from the local filing system this is not possible. However, you may be able to get around this with the http-equiv <meta> tag:
Authors who are unable to support signaling via HTTP headers can use tags with http-equiv="X-Content-Security-Policy" to define their policies. HTTP header-based policy will take precedence over tag-based policy if both are present.
Answer after question edit
Look into the Referer or Origin HTTP headers. Referer is available for most requests, however it is not sent from HTTPS resources in the browser and if the user has a proxy or privacy plugin installed it may block this header.
Origin is available for XHR requests only made cross domain, or even same domain for some browsers.
You will be able to check that these headers contain your domain where you will want the scripts to be called from. See here for how to do this with htaccess.
At the end of the day this doesn't make it secure, but as in your own words will make it a little bit harder to achieve.

How to restrict access to a resource based on domain

I've got a theoretical problem I'd like to solve. Imagine I want to reference an external resource from within an HTML document. However, I want the behaviour when following the link to vary depending on the domain of the referring page (the page with the link).
e.g.
A page hosted at http://somedummydomain.com/mypage.html contains a link to a resource http://someotherdummydomain.com/mydoc.pdf?key=123456789.
When a user clicks on the link to mydoc.pdf, I would only like mydoc.pdf to be returned (200 OK) if the referrer is somedummydomain.com - if it's any other domain then return 401 NOT AUTHORIZED. The significance of the key in the query params is that the application serving mydoc.pdf will, internally, have associated that key with the somedummydomain.com domain, thus stipulating that the resource can only be accessed via that domain.
Obviously I could check the referrer, but it's trivial to spoof the referrer in the HTTP headers so, were I genuinely trying to lock something down, the referrer header is not going to be satisfactory.
I'm kind of assuming that JavaScript would have to come into play in some way? I'm judging that based on things like the Google Analytics JS code that will only accept events occurring on a page hosted at a pre-registered domain.
Does anyone know how this type of behaviour could be achieved?

Is it possible to circumvent the same origin policy if you don't have control of the second origin?

This SO post lists numerous ways to circumvent this poilicy.
However, I can't tell if any of these are applicable to when you don't have access to the second origin.
Particularly this one, 3rd answer down, you insert a script that calls a script form the second origin.
<script src="http://..../someData.js?callback=some_func"/>
But in general do any of these methods allow circumvention when you are on origin one...and need access to origin two?
Yes, you can circumvent the Same Origin Policy without controlling the second server, but you can't do it without the cooperation of the owner of the second server. Often, as in your example, this is done by cooperating with the JSONP conventions. There is no other way of doing this without proxying the requests to the second server through the first.
Obviously this can't be possible, otherwise the policy would be useless. It's all about preventing you from pulling data from a third host, which is exactly what you are trying to do.
Note that browsers have no notion of what is part of the "private" local network and what is part of the "public" global internet. So this policy exists to prevent arbitrary Javascript code from accessing resources on your local network.
NO, that's the entire point. The SOP can be turned off only if the server specifically allows it thru either CORS or something like JSONP.
Inserting scriptlets is an attack (regardless of if your intentions are good). If I owned a domain and someone did that, they would be banned and reported to the authorities.
The closest you can come is to use server side proxy (i.e. have your js make requests your server, which in turn makes requests to the third party).

Test url availability with javascript

Is it possible through jQuery (or plain javascript) to test if a webpage on another domain is available?
I tried getting the response headers with an ajax-call but I get an error no matter what site outside my own domain I test.
So do I really need a proxy script on my server or would I be able to skip that request?
Is it possible through jQuery (or plain javascript) to test if a webpage on another domain is available?
Due to same origin policy restriction you need a proxy/bridge on your server unless the remote server implements JSONP which obviously we cannot assume for the general case.
You can create an <img> tag that points to an existing image on the external domain.
If the onerror event fires, image, and perhaps the entire site, is down.
If it fires after 5 seconds or so, it probably timed out, so the entire site is likely to be down.
Yes, you need to use a proxy script on your server. JavaScript cannot be used in a browser to request resources across domains, as per the same-origin policy.

How to get the url of a webpage that is embedding another page in an iframe on a different origin domain

Webpage A is embedded in an iframe inside of webpage B. A and B are on two different domains and therefore the same origin policy prevents A from accessing properties of B like so;
location = window.top.location.href // emits a "Permission denied" error
Is there any other way for A to get B's url?
No
If you have control over both domains, you can try a cross-domain scripting library like EasyXDM, which wrap cross-browser quirks and provide an easy-to-use API for communicating in client script between different domains using the best available mechanism for that browser (e.g. postMessage if available, other mechanisms if not).
Caveat: you need to have control over both domains in order to make it work (where "control" means you can place static files on both of them). But you don't need any server-side code changes.
In your case, you'd add javascript into one or both of your pages to look at the location.href, and you'd use the library to call from script in one page into script in the other.
Another Caveat: there are security implications here-- make sure you trust the other domain's script!

Categories

Resources