0

We have an mp3 player that runs via an iFrame, not our choice but thats how we're stuck with it. We want to prevent other people simply embedding the iframe on their site.

What would be the best way to do this? We're running nginx so no .htaccess. The mp3 player is made up of php files and we need to keep running it in an iframe.

Is there anyway to lock the specific mp3 players php file (in this case html5player.php) to only be able to be executed on our server or domain name? Surely there is a way to do that in nginx? But then of course, if they embed the iFrame it will think it IS running on our server anyway wont it?

Everything solution I've thought of has fallen down somewhere along the way, so input much appreciated.

Danny Shepherd
  • 177
  • 1
  • 12
  • 1
    http://en.wikipedia.org/wiki/Framekiller and https://developer.mozilla.org/en-US/docs/HTTP/X-Frame-Options – ceejayoz Feb 06 '13 at 17:32

2 Answers2

1

I'm not an expert of NGINX but this could work theoretically:

location ~* \urltoyourplayer?$ {
  valid_referers none blocked yourdomain.fqdn;
    if ($invalid_referer) {
      return 403;
    }
}

This should prevent embedding your player into other websites by reading the referrer URL, if it match your domain then OK, otherwise return error 403.

Martino Dino
  • 1,145
  • 1
  • 10
  • 17
  • You can read that as well: http://nginxlibrary.com/hotlink-protection/ – Martino Dino Feb 06 '13 at 17:57
  • Added this as… location ~* \.http://themixtapesite.com/wp- content/plugins/amazon-s3-cloud-mp3-player/html5/html5big.php?$ { valid_referers none blocked http://themixtapesite.com.fqdn; if ($invalid_referer) { return 403; } } But can still run the player from my other URL, I also have the hotlinking script in my nginx conf files blocking php, mp3, images from appearing on anything other than my URL as well and still, the player embeds on my other domain! – Danny Shepherd Feb 06 '13 at 21:21
  • The location you're using is wrong, there goes the proper one: `/wp-content/plugins/amazon-s3-cloud-mp3-player/html5/html5big.php` The proper line is: `location /wp-content/plugins/amazon-s3-cloud-mp3-player/html5/html5big.php {` – Martino Dino Feb 06 '13 at 21:27
  • Thanks Martino, I'll try that now… From that link you sent me I tried… `location /wp-content/plugins/amazon-s3-cloud-mp3-player/html5/ { valid_referers none blocked themixtapesite.com *.themixtapesite.com; if ($invalid_referer) { return 403; } }` Which should lock the entire folder, is my location incorrect there too? – Danny Shepherd Feb 06 '13 at 21:31
  • I believe it's correct, yet I'm not sure that it will work for subsequent folders (like `html5/folder/file`), will try that now and post back the answer. – Martino Dino Feb 06 '13 at 21:33
  • Tried your code and and the second one AND a hotlinking code, all of them at the same time, doesn't return any errors when I reload nginx but doesn't do ANYTHING. I've got these running now… – Danny Shepherd Feb 06 '13 at 21:36
  • `location /wp-content/plugins/amazon-s3-cloud-mp3-player/html5/html5big.php { valid_referers none blocked themixtapesite.com.fqdn; if ($invalid_referer) { return 403; } } location /wp-content/plugins/amazon-s3-cloud-mp3-player/html5/ { valid_referers none blocked themixtapesite.com *.themixtapesite.com; if ($invalid_referer) { return 403; } } ## Stop Image and Document Hijacking location ~* (\.php|\.mp3|\.css|\.png|\.jpg)$ { if ($http_referer !~ ^(themixtapesite.com) ) { return 405; } } ` – Danny Shepherd Feb 06 '13 at 21:37
  • I'm putting them in the server block of the.conf is that makes any difference? Nginx v1.2.2 – Danny Shepherd Feb 06 '13 at 21:38
  • yep they should go under the server {...} directive – Martino Dino Feb 06 '13 at 21:38
  • well thats where they are, so i'm at a loss :/ – Danny Shepherd Feb 06 '13 at 21:39
  • Maybe someone better than me in nginx will help us. – Martino Dino Feb 06 '13 at 21:41
  • There is no sever block in the actual nginx.conf but everytime I try to add it, it tells me it shouldn't be there… There is a server block in lots of other conf files, i'll try adding it to any server block I find! – Danny Shepherd Feb 06 '13 at 21:42
  • http://wiki.nginx.org/ServerBlockExample – Martino Dino Feb 06 '13 at 21:43
  • I've totally no idea, I've put it in every single file with sever block in, I've now added a server block to the nginx.conf file without error and still nothing. I'm running `/etc/init.d/nginx reload` every time and i'm restarting nginx, maybe thats not enough?? – Danny Shepherd Feb 06 '13 at 21:52
  • I've even rebooted the server now just to make sure - nope. Still doesn't work. Totally stumped now! – Danny Shepherd Feb 06 '13 at 21:57
1

Sounds like a job for the X-Frame-Options header:

add_header X-Frame-Options SAMEORIGIN;

(Applied to a location matching the file in question, obviously)

You could also add the header in PHP, which may be easier.

Make sure to add the header exactly once, or it will be ignored by some browsers, causing a lot of "fun" when debugging. See bug report for Chrome, bug report for Firefox.

Jan Schejbal
  • 171
  • 3
  • Hmmm, I tried this, added it to my nginx file, which it read fine, but I can still load up on my other domain? – Danny Shepherd Feb 06 '13 at 21:08
  • Which browser are you using to test? Are you sure the header is being delivered? (Check with Wireshark, Firebug or the equivalent built-in tool in Firefox/Chrome.) – Jan Schejbal Feb 06 '13 at 23:00
  • Chrome and Safari on Mac. I added it as `` to the php file header as well as it didn't work when I added it to the nginx.conf (see above, NOTHING is having any effect in the .conf file, even simple hotlinking) But yes, didn't work when I added it as the first line of the php file either…. – Danny Shepherd Feb 06 '13 at 23:24
  • I've now added `` to every single php file the plugin calls inside the iFrame and it still loads with no problems on my other domain!! – Danny Shepherd Feb 06 '13 at 23:55
  • Enable error reporting `` to make sure you don't miss errors like "headers already sent". You need to include the header command in front of ANYTHING else, including invisible byte-order-marks many editors add to UTF8 files. – Jan Schejbal Feb 07 '13 at 08:04
  • No errors at all (I even created an error to check error reporting was working and it was) no header errors nothing. The same origin code is right at the to of the php file called by the iframe, the very first thing. – Danny Shepherd Feb 07 '13 at 11:46
  • Jan, do you think it makes a difference that we're not iframing a page here as such but calling on a php plugin to run in an iframe because it has lots of other JS and php file dependencies, or shouldn't that make a difference? I can't understand why this header option just isn't doing anything. Infact the player seems to be easily embed able anywhere no matter what protection I try! – Danny Shepherd Feb 07 '13 at 11:59
  • What do you mean by "calling a PHP plugin to run in an iframe"? There is an ` – Jan Schejbal Feb 07 '13 at 14:01
  • Thats correct Jan, here is the full iFrame, you SHOULDN"T be able to embed it on your, but you can… `` It should only run on themixtapesite.com but I can run it here easily - http://www.danielshepherd.co.uk/stolen-player-test/ – Danny Shepherd Feb 07 '13 at 14:10
  • The header is sent three times. Make sure it is sent exactly once, or some browsers (Chrome, notably, as well as older Firefox versions) will ignore it. It works correctly (i.e. the player does *not* work) in current Firefox. Added that to the answer. – Jan Schejbal Feb 07 '13 at 14:40
  • Really Jan? It works in current version of Firefox on the Mac - I just loaded up http://www.danielshepherd.co.uk/stolen-player-test/ fine. I can't see where in that php file the header is sent other than explicitly with the code I've added :/ There are no other – Danny Shepherd Feb 07 '13 at 15:17
  • Right ok, so far it only works in Firefox on Windows latest version. I've removed the – Danny Shepherd Feb 07 '13 at 15:23
  • If its being added twice now when you look, maybe my nginx server is indeed reading its .conf? – Danny Shepherd Feb 07 '13 at 15:26
  • I've now removed php header('X-Frame-Options: SAMEORIGIN'); from all instances, and it still doesn't appear in Firefox on Windows, put it appears it all over browsers on other OS, so I'm guessing the reason it doesn't appear in Firefox isn't to do with the X-Frame? – Danny Shepherd Feb 07 '13 at 15:50
  • Currently, there are two copies of the SAMEORIGIN header. You can see this if you click the request on the network tab of the chrome web developer tools. – Jan Schejbal Feb 08 '13 at 00:18
  • I wonder if this could be because the page is Ajax refreshed Jan? But the weird thing is I don't have Sameorigin set anywhere in any files at the minute!? – Danny Shepherd Feb 08 '13 at 12:32
  • Jan, finally! My Nginx server WAS setting it from the start, it seems because its Ajax refreshed it must have been setting it twice on the page. So I removed it from the server and set it just in the php and now it does work. I'd also got some php code to work which checks the HTTP referrer, now which it says this isn't reliable on PHP I tried in all browsers on PC and Mac including IE7-IE10, Canary, Opera and Comodo Dragon. It worked on all of them, so i'm not sure where it wouldn't work. – Danny Shepherd Feb 08 '13 at 12:42
  • It probably isn't caused by an Ajax refresh, but something else. Referer is unreliable because some users and some internet security suites disable it for privacy reasons. A referer can be "faked" to look blank (i.e. as if the user disabled it) with moderate effort. While it is a sufficent tool to make content stealing more difficult, it is unsuitable for security purposes like to detect a user is already logged in, and I suspect the PHP warning is about that. – Jan Schejbal Feb 08 '13 at 20:40
  • So you'd suggest X-Frame as a more reliable method? (I presume it doesn't check browser refer to check for same origin?) the 3rd way to do it was with JS, similar to the php method, but rather than check HTTP refer, it checks that the top.window (or address bar) has the same URL as the php file, I presume thats a more secure way of doing it (or rather will muck up for a lot less users) perhaps a combination of that and x-frame would cover all browsers? – Danny Shepherd Feb 08 '13 at 21:34
  • top.window may become easy to circumvent with the sandbox attribute. X-Frame will prevent embedding in most current browsers (it was made just for that, as embedding can be a security risk), so it is the way to go. It will certainly suffice to prevent people from embedding your player. They may "steal" it in other ways, but that is way beyond this comment. I'd suggest to deal with when it happens, it if it ever happens. (Sidenote: Please remember to vote on answers and accept one of them if your problem is solved.) – Jan Schejbal Feb 08 '13 at 22:52