3

I host a javascript that site owners run on their website. My server is a LAMP stack. I'm trying to secure the script for approved web sites. What are some ways to do this? I'm currently looking for $_SERVER['HTTP_ORIGIN'] and Access-Control-Allow-Origin to allow access. Is this the most secure way to do this , can be spoofed?

My javascript is to provide a service and needs to be secure. Think google analytics - the js that people put on their web site.

php_needs
  • 45
  • 4
  • Maybe see https://stackoverflow.com/questions/4566378/how-secure-is-http-origin – Syscall Feb 16 '18 at 18:39
  • 1
    of course it can be spoofed. everything can. sanitize and validate all input. CORS is not used by script tags, just ajax. – dandavis Feb 16 '18 at 20:41

3 Answers3

0

According to web standard, cross origin request made through XMLHttpRequest (AJAX) are not permitted to avoid one domain accessing another resource from a different domain for security reasons. This is applicable to requests initiated through XMLHttpRequest object. The origin header was brought to help allow cross domain resource sharing while still maintaining security checks on the resource and will only be sent for requests that are considered as cross domain requests.

For your case, checking on Origin header will be wrong since requests for your hosted script is not initiated through XMLHttpRequest but rather through the src attribute of script elements.

The best practice will be to check for the referer header. This is almost sent for every request and is also good to check on it when implementing Cross site request forgery defence.

Capture the host from the sent referer header using regex. Then check the host against your list of allowed hosts

Deny access if captured host is not white listed by sending 404 or 403 response back as you deem fit.

$allow = FALSE;
$allowed_hosts = ['http://www.example.com/']; //note the ending slash
$matches = [];
$referrer = array_key_exists('HTTP_REFERER', $_SERVER)? $_SERVER['HTTP_REFERER'] : NULL;
if (!is_null($referrer) && preg_match('/^(http[s]?\:\/\/[^\/]+\/)/', 
$referrer, $matches)) {
    $host = strtolower($matches[1]);
    if (in_array($host, $allowed_hosts)) {
        $allow = TRUE;
    }
}
if ($allow) {
    header("Content-Type: text/javascript");
    header('Cache-Control: max-age=86400');
    echo file_get_contents('path to javascript');
}
else{
   header("HTTP/1 403 Forbidden");
   exit;
}
  • So the script fails on any browser which has referers turned off, and frequently fails in Safari due to its buggy referer handling. – symcbean Feb 17 '18 at 01:09
  • 1
    Can you give a test scenario to prove that safari has buggy referer handling. All major browsers send the referer header, even when working on your local machine (localhost). To be satisfied, if the referrer header is not present, request should be aborted. That is the essence of white listed defence. Since the javascript is not a public resource according to him, I believe the solution proffered will achieve it – Harrison Ifeanyichukwu Feb 17 '18 at 05:39
  • Thank you for sharing that. From the IBM report, it says that the report is uproven with no test prove. That was at 2014. When following web standard, one or two products will always break the standard. But it gets fixed with time. So I see no reason why I should not hold on to the referer header – Harrison Ifeanyichukwu Feb 18 '18 at 07:29
0

As always, it depends on what you want to protect against.

What will keep a user from forging a full request with an authorized referer/origin, downloading your javascript, and hosting it on their server?

Also note that under some circumstances, referer/origin can be spoofed.For example certain browser extensions (if installed of course) some old versions of Java or Flash plugins, maybe other things as well allow such forgery. As an extreme example, a rouge consumer of your content may ask his visitors to first install a browser extension which "gives access to his content", when in reality it allows him to forge referer/origin.

If you really want to secure your content in the sense that you only want to allow authorized clients to download it, unfortunately the only way to achieve that is authentication of some sort. Now obviously you don't want to authenticate the enduser, but the website that sent him, which is an interesting scenario, and is beyond the scope of this answer.

Besides that, probably the most common and best-practice-like thing you can do is you can provide authorized websites with something similar to an api key, the way Google do it in their services. The key is plaintext in any customer page, but if you have proper monitoring in place, you can revoke abused keys. Note that this is not authentication, anybody can copy the host website key from their page source, but you will have a chance to discover abuse, for example not everybody will install a browser extension or plugin, and you will see mismatching referers on the given api key. In many scenarios, this may be good enough. Note that the difficulty is not the api key part, but effective monitoring.

Gabor Lengyel
  • 14,129
  • 4
  • 32
  • 59
0

Your model of "secure" appears to be predicated on preventing other people from using your code. There are some obvious solutions to this but they depend on you breaking what the end-user is likely to consider as secure.

You already have legal protection against people using your code without licence. And the methods you describe provide limited technical protection.

If you really think your code is that wonderful/valuable then move the logic server side and write a basic renderer in JavaScript to connect over websockets

symcbean
  • 47,736
  • 6
  • 59
  • 94
  • My javascript is to provide a service and needs to be secure. Think google analytics - the js that people put on their web site. – php_needs Mar 01 '18 at 20:05
  • 1
    Nothing you send to the client can be protected from actions by the user. You still haven't provided a clear explanation of what "secure" means: if you can't explain the problem there's little chance of anyone being able to help you solve it. – symcbean Mar 01 '18 at 22:12