Cross Domain Request to localhost - javascript

DISCLAIMER: I've already looked at various approaches to solve my issue, so please read this before labeling this as a duplicate question
I have a javascript running on https://xyz.com which has to retrieve information from an application ABC running on the user's local machine say port 8080.
My constraints are that I cannot modify the HTTP headers emanating form the ABC nor do I want the user to install another application which will be a conduit to route my requests through to ABC.
Cross-Domain/Window Messaging Options
a) window.postMessage: Ruled out since I cannot have script running on the local machine
b) XDR Object (IE) or Access-Control-Allow-Origin (Firefox,Safari et al): Ruled out since I cannot modify the header
c) JSONP: Again this will not work since I am unable to enclose the response within the function name
As a workaround, only meant for testing I've added the http://xyz.com to the trusted list and have enabled Access Data Across Domains for sites on this list. AFAIK, this option is only available on IE 5+ browsers. This workaround allows me to send and receive messages from http://127.0.0.1:8080
My question is two-fold
1) If I were to continue with the above approach when I go into production what are the security implications that I'm exposing the user to? Can I plug those holes?
2) Are there any other options that I can pursue to achieve my objective.
PS: I would like to be as far away from ActiveX or Flash as possible, but in case that is the only workable alternative to my current approach then I'll have to toe the line
Cheers

If the local application could serve a single html document, to act as a bridge, then you could easily use Cross-Document Messaging (for instance with easyXDM) together with ajax requests from this document to do this. This is a very simple approach and one commonly used.
easyXDM actually comes with such a document, you can read about it here.

I think that the easiest would be to put a server script on https://xyz.com which will act as a bridge between the javascript file and ABC. Then the javascript file will simply send an AJAX request to it's own server script which will take care of fetching the information from the remote domain. The only other viable solution which would work among most browsers and which doesn't require using some client technology like Flash or ActiveX is JSONP but you have ruled this out because you have no control over the remote domain.

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.

CORS with IE11+ Access Denied with SSL to localhost

The Very Short Version: is anybody successfully requesting local resources via AJAX, in IE, over SSL? I cannot solve getting an "access denied" error.
The Longer Version:
I am using AJAX to retrieve JSON from an application that runs a local web service. The web service channel is encrypted so that if the remote site is being served over HTTPS, no "insecure resource on a secure page" errors appear.
So, in the address bar is a remote site of some sort... mysite.com. It is receiving information from https://localhost/.
The web service is setting correct headers for CORS and everything works in Chrome and Firefox. In IE, if I put my https://localhost resource into the address bar, the correct resource is returned and displayed. However, when using AJAX (not just the address bar), a security setting in IE is denying access. This is documented (in part) here:
Access denied in IE 10 and 11 when ajax target is localhost
The only proper solution in one reply is to add the requesting domain (mysite.com in this case) to the trusted sites. This works, but we would prefer to not have user intervention... pointing to a knowledge base article on how to add a trusted site is hardly a great user experience. The other replies to that question are invalid for the same reasons as below-->
Some more stumbling around and I discovered this:
CORS with IE, XMLHttpRequest and ssl (https)
Which had a reply containing a wrapper for AJAX requests in IE. It seemed promising, but as it turns out, IE11 has now deprecated the XDomainRequest API. This was probably the right thing for Microsoft to do... but now the "hack" workaround of adding a void onProgress handler to the XDR object is obviously not an option and the once-promising workaround wrapper is rendered null and void.
Has anybody come across either:
a) a way to get those requests through without needing to modify the trusted sites in IE? In other words, an updated version of the workaround in the second link?
b) as a "next best" case: a way to prompt the user to add the site to their trusted zone? "mysite.com wishes to be added to your trusted zones. Confirm Yes/No" and have it done, without them actually needing to open up their native settings dialogues and doing it manually?
For security reasons, Internet Explorer's XDomainRequest object blocks access (see #6 here) to the Intranet Zone from the Internet Zone. I would not be surprised to learn that this block was ported into the IE10+ CORS implementation for the XMLHTTPRequest object.
One approach which may help is to simply change from localhost to 127.0.0.1 as the latter is treated as Internet Zone rather than Intranet Zone and as a consequence the zone-crossing is avoided.
However, you should be aware that Internet Explorer 10+ will block all access to the local computer (via any address) when a site is running in Enhanced Protected Mode (EPM)-- see "Loopback blocked" in this post. Currently, IE uses EPM only for Internet sites when run in the Metro/Immersive browsing mode (not in Desktop) but this could change in the future.
No, there's no mechanism to show the Zones-Configuration UI from JavaScript or to automatically move a site from one zone to another. However, the fact that you have a local server implies that you are running code on the client already, which means you could use the appropriate API to update the Zone Mapping on the client. Note that such a change requires that you CLEARLY obtain user permission first, lest your installer be treated as malware by Windows Defender and other security products.
So, in summary, using the IP address should serve as a workaround for many, but not all platforms.
Since those are two different domains, one solution would be to create an application which proxies the requests in the direction you want.
If you have control over the example.com end, and want to support users who bring their own localhost service, this would be harder, as you would have to provide more requirements for what they bring.
If however, you have control over what runs in localhost, and want to access example.com, and have it access the localhost service, set up redirection in your web server of preference, or use a reverse proxy. You could add an endpoint to the same localhost app which doesn't overlap paths, for example, route http://localhost/proxy/%1 to http://%1, leaving the rest of localhost alone. Or, run a proxy on e.g. http://localhost:8080 which performs a similar redirection, and can serve example.com from a path, and the API from another.
This winds up being a type of "glue" or integration code, which should allow you to mock interactions up to a point.

Javascript in browser IS able to use sockets/get info from web by itself?

Is it possible to open sockets and get data from web in JavaScript.
My aim is: to work with web data using JS.
I have looked for XmlHttp/AJAX solution, but I have found one note, that AJAX can be used only for calling localhost programs, which will be used as proxy and then only returns data from web.
It's because of sandbox model in browsers, which don't allow to work with sockets/other sites from JavaScript, and it works only in localhost.
Are there any solutions with JS to work with other world?
Your issue is due to cross domain request security, where you can't asynchronously get data from a domain which doesn't match the current host (this includes subdomains). You can however use jsonp, but this relies on the service that you're quering to supply the data in a jsonp format (a function call with the json data as a response).
If you have no control over the services you're requesting (which i assume you don't), you can use a javascript library, such as YUI or jQuery to perform the cross domain request for you (which typically uses Flash as the data proxy). However this will only work if you the site in question allows cross domain requests from your domain (defined in crossdomain.xml).

Cross-domain POST with integrated security

I run a site A and I want to be able to POST data to site B, which is hosted on a different subdomain. Now I have complete access to A, but cannot modify B at all.
My requirements are:
supports file upload
does not refresh browser on POST
uses Windows integrated security
works in IE 7/8 (does not need to support any other browsers)
What's the best way to accomplish this?
What I've tried:
Ideally this could be done in a simple AJAX call. However the current standard does not support sending binary data (supported in the XMLHttpRequest Level 2 standard, which is not implemented in IE yet).
So the next best thing is to POST to a hidden <iframe> element. Now I've tried this but the server on site B won't accept the data. I looked at the request and the only discrepancies that I found were the referer URL and the integrated authentication. The referer URL might have to be spoofed, which cannot be accomplished by this method. Also for some reason the authentication isn't being negotiated. I'm not 100% sure why.
Ideas:
I'm thinking of creating a proxy page on the server that I run (site A) that forwards the request to site B. Site A also uses integrated security. I don't see anything wrong with this, but I'm not sure if this is the best way to go. Will there be any authentication issues if I just forward the request over?
Using a proxy seems to be the only thing which can work in your case. If you want to make a get request then it can be done using JSONP provided that the server supports JSONP. To make the <iframe> hack work the server should send the headers as
Access-Control-Allow-Origin:*
which is not the case with you.
So using a proxy seems the solution

Retrieve a cross domain RSS(xml) through Javascript

I have seen server side proxy workarounds for retrieving rss (xmls) from cross-domains. In fact this very question addressess my same problem but gives out a different solution.
I have a constraint of do not use a proxy to retrieve rss feeds. And hence the Google AJAX Feed API solution also goes out of picture. Is there a client-only workaround for this problem.
JSONP is the solution for requests that respond with JSON output. But here, I have RSS feeds which can respond with pure xml .
How do I solve the problem.
Use something like Yahoo! Pipes to serve as your proxy and translate the RSS XML into a JSON response.
Here is an article with instructions and code samples that explains how to do it: Yahoo Pipes--RSS without Server Side Scripts.
If you have control over both domains, you can try a cross-domain scripting library like EasyXDM, which wraps cross-browser quirks and provides 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.
Another Caveat: there are security implications here-- make sure you trust the other domain's script!
Right now there really isn't a cross-platform solution for cross-site scripting. Do you have control or access to the RSS feeds? If so, why not simply respond with JSON and use JSONP?
There are other things coming down the pike with HTML5, like cross-site messaging (referred to as Cross-Document Messaging) that may be capable of delivering a payload of XML, but last time I checked, they hadn't even fully decided on a size limit for the messaging.
You can see the spec here: http://dev.w3.org/html5/spec/Overview.html#crossDocumentMessages
A solution for cross-domain calls without a server-side proxy is to use a SWF component.
You can script yourself one or use the readily available FLSend
The component uses ActionScript's URLRequest to call remote domains and ExternalInterface to communicate with the JavaScript methods that render your content.
The only way I can think of would be to embed a signed java applet on the webpage to retrive the xml and use javascript to interface with that. I'm not even 100% certain what the java security model is for that at present though but I think it would work.

Categories

Resources