views:

1457

answers:

8

I am creating a small web page using PHP that will be accessed as an IFRAME from a couple of sites. I'm wanting to restrict access to this site to work ONLY within the "approved" sites, and not other sites or accessed directly. Does anyone have any suggestions? Is this even possible? The PHP site will be Apache, and the sites iframing the content will probably be .NET.

Just to clarify, any site can view the page, as long as it's iframe'd within an approved site. I want to block people from accessing it directly. I'm thinking cookies might be a solution, but I'm not sure.

A: 

Unfortunately this isn't going to be possible.

Using Javascript you can check to see if your page is embedded in another frame, but this won't be foolproof as Javascript can be turned off in some people's browsers.

For example, you can run the following javascript to reparent your page if that's the intention:

if (top.location != location) {
  top.location.href = document.location.href ;
}
Gareth
I was hoping for some sort of functionality like the HTTP_REFERER variable, but I don't think there is any. :-(
m0j0
The HTTP_REFERER can't be trusted - it can changed or hidden at will.
Tom Ritter
You could use JavaScript to load the end-page, too, so that they require JS enabled to use it, thus you can use JS to prevent it being loaded in unauthorised pages.
staticsan
A: 

Could you not check the $_SERVER['HTTP_REFERER'] to ensure it includes a certain string?

if (strpos('http://example.com', $_SERVER['HTTP_REFERER']) !== false) {
    // allowed
}

In your case you might want to parse out the address first, then check if in_array().

This won't be fool proof as people can fake the referrer, BUT maybe you could do some kind of 1 use keys with some other communication between the 2 servers. If the key has been used, then no go.

Darryl Hein
+1  A: 

Thinking about this... I'm not convinced this is completely secure, but here's a shot while I think about it more -

The only way you could do this, is if you control the sites it would be embedded in. If you control them, you could pass the time, encrypted, from the frameset to the frame:

 <iframe src="http://yourdomain/frame.php?key=p21n9u234p8yfb8yfy234m3lunflb8hv" />

frame.php then decrypts the message to find the time within a small delta (say 10 seconds). Because frame.php knows only acceptable sites could have encrypted the time, it knows it's okay to display itself. Otherwise, it outputs nothing.

Anything else, whether it's javascript or HTTP_REFER, can be spoofed, turned off, or circumvented.

And in fact, with that url, an attacker will be able to show your frame anywhere, as long as the user loads it within 10 seconds. So the attacker would just scrape the accepted site, and grab the key. If that threat model is unacceptable to you - then there really is nothing you can do (except maybe an even more complicated protocol).

Tom Ritter
+1  A: 

I would implement this the same way that google implements adsense. Instead of having them embed the iframe code in their site, instead have them embed some javascript which includes an account number:

<script type="text/javascript"><!--
myiframe_client = "12345";
myiframe_width = 728;
myiframe_height = 90;
//-->
</script>
<script type="text/javascript"
src="http://www.example.com/scripts/show_iframe.js"&gt;
</script>

At least this way you can manage who displays your iframe contents on a per-account basis. If somebody unauthorized attempts to use your iframe, you can disable the account. You can also examine properties of the document through javascript (within the security limitations of the browser) to prevent unauthorized access.

Keltex
Hmmm....I will look into this method.
m0j0
Unfortunately this is somewhat easy to spoof, as the account number will be visible in the JavaScript file. That migh be good enough depending on how secure you need i to be.
Rontologist
My thought was that you could add security in your .js file to validate the client. E.g. check the document.domain property, etc.
Keltex
+1  A: 

Screen scraping might be a possible solution here.

Set up the access list on your site to accept only requests coming from the approved sites web servers and issue a security token to them. That is the easy part.

The dev team on their end will need to setup a relaying servlet to get your content and then display it to the users (after rewriting any pertinent urls).

This can be quite involved, but you would be better able to control who accesses the site. Additionally, any security token that you issue will not be visible to the web user, since it should only be transmitted between the two webservers.

Rontologist
A: 

Thanks for all the great ideas! I think the solution I'm going to go with is a session cookie set by the approved "iframing" site. Someone really determined will still be able to get the content, but I think I can prevent most of the abuse by coming up with a decent "secret" algorithm based on some sort of shared secret on both sides, and have the approved site set a session cookie that will be read by my PHP site. If the cookie is valid and meets my criteria, I'll display the contents, otherwise I won't. The information I'm protecting isn't mission-critical, I'm just trying to prevent it from being abused.

m0j0
I don't think that's going to work. If the cookie is set by the page, you won't be able to see the cookie in your IFRAME because they are in different domains.
Keltex
Actually the sites will be in the same domain name, so I *THINK* it will work. It's just that my site will be Apache/PHP, and the other site will be .NET.
m0j0
A: 

You can MD5 (or encrypt for better security) the client IP using a secret salt + date and pass this as a parameter in iframe src url. In the iframe you do the same thing and check if the result is the same as the parameter; if not, deny access

Catalin DICU
A: 

Can you pass a PARAMETER on a link from menu page (let's say a menu link) calling a database record to a result page and displaying this result page into the same menu page using an iFrame ???

Any help would be apreciated.

Pardall