0

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

Oliver
  • 23,072
  • 33
  • 138
  • 230

2 Answers2

1

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.

jpw
  • 343
  • 2
  • 9
0

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.

SilverlightFox
  • 32,436
  • 11
  • 76
  • 145
  • Thank you. The problem is that seem not applicable. If a user gets the code of the call, puts it into it's own HTML file on its computer, and open it, it will sure not put the meta in it. So as the distant JS script do not have meta (and even if it have one, it's so so easy to remove it from inside the browser, or copy it to local and modify it), and as the php is called by this script, so.... this kind of security may be ineffective. (See my Edit) – Oliver Jul 18 '14 at 16:42
  • Thank you. I've tried the method blocking the.php script, the .js, both, and in all case, if it blocks the hack tentative, it also block the legal ones. I've made a try, and I can see that in the .php script, the HTTP_HOST is the domain even when called from the single file calls from c:/. – Oliver Jul 18 '14 at 22:08
  • @Oliver - Yes `HTTP_HOST` is the server where it is running. I mentioned using `referer` or `Origin` headers. Use [getHeader](http://php.net/manual/en/httpresponse.getheader.php). – SilverlightFox Jul 18 '14 at 22:22
  • I've tried RewriteEngine On RewriteCond %{HTTP_HOST}@@%{HTTP_REFERER} !^([^@]*)@@https?://\1/.* RewriteRule .*\.pdf [NC,F] Is this what you mean ? This do not work, it blocks any request from anywhere – Oliver Jul 18 '14 at 22:48
  • @Oliver: For a start are your headers being sent as expected? – SilverlightFox Jul 19 '14 at 00:01
  • The problem is that I'm not used with blind debugging. The PHP script is called asynchronously by the js one, and has no user interface. So could you help me on how to easily check the result of getHeader when I cannont print it ? – Oliver Jul 19 '14 at 00:37
  • @oliver Browser dev tools are your friend. – SilverlightFox Jul 19 '14 at 07:57
  • Hmmm... do you have an advice ? I Have FireBug installed, XDebug too, but I'm not very familiar with them – Oliver Jul 19 '14 at 09:37
  • @Oliver: Maybe you could add debugging with FireBug as a separate question as SO is more of a QA site than a discussion forum. – SilverlightFox Jul 29 '14 at 10:09