Unable to access iframe content (same-origin policy) - javascript

I have the following page
<!DOCTYPE html>
<html>
<script type="text/javascript">
function loopLink(i)
{
window.open($('#iframe_a').contents().find('.image-navigator-mid a').attr('href'),'iframe_a');
setTimeout(function()
{
if (i < 3) loopLink(i+1);
}, 5000);
}
// Wait for the page to load first
window.onload = function() {
var a = document.getElementById("mylink");
a.onclick = function() {
loopLink(0);
return false;
}
}
</script>
<iframe src="http://nanofate.us/content/fate-new-hair-style#node-inner" width="500" height="500" name="iframe_a" id="iframe_a"></iframe>
<br />
<a id="mylink" href="">Execute</a>
the idea is that in it's current form, when you click Execute, the javascript will cause the iframe to use the "previous" link 4 times, waiting 5 second each time, however when i click the link it just reloads the page and even after waiting 10 seconds the iframe is doing nothing
i am wondering what i have done wrong

Due to Same Origin Policy restrictions, you can not access contents of iframe if it is running a page from another domain. There are solutions to same domain policy like
Opening a page via a proxy
Check out Tomodo. It is just to give you a hint how they used proxy to bypass same origin policy constraint and access iframe content. So the implementation idea goes like this
Create a proxy and host it at a.com/proxy
Host your main page at a.com/index.html
Now, request your proxy to give you content of iframe_url something like this a.com/proxy?url=iframe_url.com
Please note this is not a trivial task and you may have to handle a lot of cases at your proxy like handling relative URLs, cookie reading by iframe_url etc etc.
So go for it only if you need it desperately.
Another solution might be this:
If you want to download some images for a particular domain, just ask your server side code to it for you. Your backend code will fetch the html of page and use some HTML parser like
BeautifulSoup for python (Documentation Link)
Jsoup for Java (Documentation Link)
to parse img tags and extract the source and fetch the images and download them.
PS: Just for some good information, please read Ways to circumvent same origin policy

I think what you are doing is subject to the same origin policy. This should be the reason why you are getting permission denied type errors.

Related

print a pdf via iframe (cross domain)

I need to print a PDF... But I get an error
Is there a workaround? I just need to print a PDF file with one click
error:
Uncaught SecurityError: Blocked a frame with origin "https://secure.domain.com" from accessing a frame with origin "https://cdn.domain.com". Protocols, domains, and ports must match.
code:
var iframe = $('<iframe src="'+url+'" style="display:none"></iframe>').appendTo($('#main')).load(function(){
iframe.get(0).contentWindow.print();
});
The error you are dealing with is related to cross-domain protection and the same-origin policy.
In your case, you can print an cross-domain iframe if you nest this iframe in another local iframe that we can call a proxy iframe.
Since the proxy iframe is local and have the same origin, you can print it without any issue and it'll also print the cross-domain iframe.
See below for an example:
index.html (container)
$(function() {
var url = 'proxy.html'; // We're not loading the PDF but a proxy which will load the PDF in another iframe.
var iframe = $('<iframe src="' + url + '"></iframe>').appendTo($('#main'));
iframe.on('load', function(){
iframe.get(0).contentWindow.print();
});
});
proxy.html (proxy)
<body>
<iframe src="http://ANOTHER_DOMAIN/PDF_NAME.pdf"></iframe>
</body>
With this solution, you no longer have cross-domain issues and you can use the print() function. The only things you need to deal with are a way to pass the PDF url from the container to the proxy and a way to detect when the iframe with the PDF is actually loaded but these depends on the solution / languages you're using.
I needed to print a PDF embedded through a data:application/pdf;base64,… iframe, and I ran into the same cross-origin issue.
The solution was to convert the Base64 contents that I had into a blob, and then use put blob's object URL into the iframe src. After doing that I was able to print that iframe.
I know link-only answers are discouraged, but copying someone else's answers into my own didn't feel right either.
There is a workaround for this.
Create an endpoint in your server to return the HTML content of the external url. (because you can't get external content from the browser - same-origin policy)
Use $.get to fetch the external content from your URL and append it to an iframe.
Something similar to this:
HTML:
<div id="main">
<iframe id="my-iframe" style="display:none"></iframe>
</div>
JS:
$.get('https://secure.domain.com/get-cdndomaincom-url-content', function(response) {
var iframe = $('#my-iframe')[0],
iframedoc = iframe.contentDocument || iframe.contentWindow.document;
iframedoc.body.innerHTML = response;
iframe.contentWindow.print();
});
C# implementation for get-cdndomaincom-url-content:
Easiest way to read from a URL into a string in .NET
You do not need proxy server for workaround. You can create proxy iframe and then dynamically create another iframe inside the proxy iframe. Then attach onload="print()" to it.
Something like this
/**
* Load iframe from cross-origin via proxy iframe
* and then invokes the print dialog.
* It is not possible to call window.print() on the target iframe directly
* because of cross-origin policy.
*
* Downside is that the iframe stays loaded.
*/
function printIframe(url) {
var proxyIframe = document.createElement('iframe');
var body = document.getElementsByTagName('body')[0];
body.appendChild(proxyIframe);
proxyIframe.style.width = '100%';
proxyIframe.style.height = '100%';
proxyIframe.style.display = 'none';
var contentWindow = proxyIframe.contentWindow;
contentWindow.document.open();
// Set dimensions according to your needs.
// You may need to calculate the dynamically after the content has loaded
contentWindow.document.write('<iframe src="' + url + '" onload="print();" width="1000" height="1800" frameborder="0" marginheight="0" marginwidth="0">');
contentWindow.document.close();
}
--Issue--
HiDeo is right this is a cross-domain issue. It is a part of CORS which is a great thing for the security of the web but also a pain.
--Philosophy--
There are ways to work around CORS but I believe in finding a solution that works for most to all cases and keep using it. This creates easier code to reason about and keeps code consistent rather then changing and creating code for edge cases. This can create a harder initial solution but as you can reuse the method regardless of use case you end up saving time.
--Answer--
The way our team handles cross domain request issues is bypassing it completely. CORS is something for browsers only. So the best way to solve all cases of this issue is don't give the reasonability to the browser. We have the server fetch the document and giving it to the browser on the same domain.
(I'm an Angular guy)
The client would say something like
$http.get('/pdf/x').then(function(){
//do whatever you want with any cross-domain doument
});
The Server would have something like what you see here HTTP GET Request in Node.js Express
It is a CORS issue . There is a library that acts as a CORS alternative , you can find it here Xdomain CORS alternative Github . It kind of by-passes CORS request seamlessly to render cross domain resources effectively.
It has a Javascript, AngularJS, as well as a JQuery wrapper too . I think this will provide you a more elegant solution, and is simple to integrate. Give it a try .

Why is "window.top.location" working in iframes?

If I can insert iframes in a forum comment, example:
<iframe src="http://badwebsite.comm/xss.html"></iframe>
cat xss.html
<html>
<head>
<script>
window.top.location = "http://badwebsite.comm/stolecred.html";
</script>
</head>
</html>
So when anyone enters this forum, it will be redirected to http://badwebsite.comm/stolecred.html/.
From this point, the stolecred.html can be an exact copy of the login page for the original forum.
After the user gave his credentials, the http://badwebsite.comm/stolecred.html can redirect it to the original website.
Question:
So allowing iframes in a forum is a very big security problem? It shouldn't be allowed in any manner? Why does a modern browser allow window.top.location to work in an iframe?
There is no limited risk (as long as there isn't a bug in the browser).
If you run the example below, you'll get the following error message in the JavaScript console of your browser:
Unsafe JavaScript attempt to initiate navigation for frame with URL 'Why is "window.top.location" working in iframes?' from frame with URL 'http://schneidr.de/misc/bad_redirect.html'. The frame attempting navigation of the top-level window is sandboxed, but the 'allow-top-navigation' flag is not set.
(Error message from Chrome, wording may be different in other browsers)
<iframe src="http://schneidr.de/misc/bad_redirect.html"></iframe>
The reason for the error is, that the browser doesn't trust JavaScript that is embedded via a frame from a different domain. Because of this it is automatically sandboxed.
To allow the JavaScript changes in an iframe you need to set the sandbox="" attribute, for this example to sandbox="allow-top-navigation". So, if you allow iframes in comments you should at least filter this attribute before saving and displaying it.
If you do this it is pretty safe to allow iframes from a security point of view. Personally I wouldn't allow it on a site I administer because I have no control over the content displayed via the iframe, which could bring me legal trouble.

Javascript to redirect URL not working

I am using an iframe reference on my site with src=https://cw.na1.hgncloud.com/crossmatch/index.do?. However, I want to have the Javascript that handles creating the URL http://www.crossmatch.com/jobs?jobPostingID=100135 to redirect to https://cw.na1.hgncloud.com/crossmatch/index.do?jobPostingID=100135 this will be invisible and seamless to the applicant.
I have created the code below, but the redirect is not happening.
<iframe id="careersiframe" src="https://cw.na1.hgncloud.com/crossmatch/index.do?" frameborder="0" marginwidth="1"
style="position:absolute;top:100px;width:800px;height:400px;border:solid 1 px">
</iframe>
This is the script I wrote to redirect the end user:
<script language="JavaScript">
document.getElementById('careersiframe').src = "https://cw.na1.hgncloud.com/crossmatch/index.do" + window.location.search;
</script>
Try to reload the iframe after changing src attribute:
document.getElementById('careersiframe').contentWindow.location.reload();
That seems right; however, there must be something else here at play. My first guess is that the issue is that you're using HTTPS in your iframe, which is a different domain (hgncloud.com) than the parent page (crossmatch.com). This is causing a cross-origin request.
If you have access to the code on crossmatch.com, I would recommend updating that to do a server redirect. It's really the best option for any redirect because you bypass the browser's security concerns. You will want to send an HTTP 301 or 307 request depending on your specific needs. Sending this is dependent on the server side programming language.
Still having issues? Remember, the issue could be something else. If you post more code or any errors you are seeing, we will be able to help better.

Checking if a website doesn't permit iframe embed

I am writing a simple lightbox-like plugin for my app, and I need to embed an iframe that is linked to an arbitrary page. The problem is, many web sites (for example, facebook, nytimes, and even stackoverflow) will check to see if is being embedded within a frame and if so, will refresh the page with itself as the parent page. This is a known issue, and I don't think there's anything that can be done about this. However, I would like the ability to know before hand if a site supports embed or not. If it doesn't, I'd like to open the page in a new tab/window instead of using an iframe.
Is there a trick that allows me to check this in javascript?
Maybe there is a server-side script that can check links to see if they permit an iframe embed?
I am developing a browser extension, so there is an opportunity to do something very creative. My extension is loaded on every page, so I'm thinking there's a way to pass a parameter in the iframe url that can be picked up by the extension if it destroys the iframe. Then I can add the domain to a list of sites that don't support iframe embed. This may work since extensions aren't loaded within iframes. I will work on this, but in the meantime....
Clarification:
I am willing to accept that there's no way to "bust" the "frame buster," i.e. I know that I can't display a page in an iframe that doesn't want to be in one. But I'd like for my app to fail gracefully, which means opening the link in a new window if iframe embed is not supported. Ideally, I'd like to check iframe embed support at runtime (javascript), but I can see a potential server-side solution using a proxy like suggested in the comments above. Hopefully, I can build a database of sites that don't allow iframe embed.
Check x-frame-options header by using following code
$url = "http://stackoverflow.com";
$header = get_headers($url, 1);
echo $header["X-Frame-Options"];
If return value DENY, SAMEORIGIN or ALLOW-FROM then you can't use iframe with that url.
Probably pretty late but what you need to do is make a request, likely from your server and look for the x-frame-options header. If it's there at all you can just open a new tab because if it is there is is one of the following: DENY, SAMEORIGIN, ALLOW-FROM. In any of these cases it's likely that you don't have access to open it in an iframe.
This subject has been discussed forever on the web with a particularly interesting (failed) attempt here:
Frame Buster Buster ... buster code needed
The bottom line is that even if you are able to construct a proxy that parses the contents of the page that you want in your iframe and removes the offending code before it is served to the iframe you may still come under "cease and desist" from the site if they get to hear about you doing it.
If you don't want your development to be widely available, you could probably get away with it. If you want your development to become popular, forget about it, and build a less underhand way of dealing with it.
Or develop it for mobile only... ;)
UPDATE: OK following on from your comment here's a bit of taster:
in javascript capture the click on the link
$("a").click(function(e){
preventDefault(e); // make sure the click doesn't happen
// call a server side script using ajax and pass the URL this.href
// return either a true or false; true = iframe breakout
// set the target attribute of the link to "_blank" for new window (if true)
// set the target attribute of the link to "yourframename" for iframe (if false)
// only now load the page in the new window or iframe
});
server side in PHP
$d = file_get_contents($url); // $url is the url your sent from the browser
// now parse $d to find .top .parent etc... in the <head></head> block
// return true or false

Issue with javascript permission denied from iframe, even when it is the same domain

I am having the eternal battle against same origin policy.
I have a registration process loaded dynamically to a page in an iframe. This process is on a different domain which I know is prohibited via the same origin policy.
However ! at the end of the process I direct the frame back to a page on the parent domain with a url variable and then fire a function to refresh the page.
I assumed that as the page is now on the same domain this would not be an issue and on firefox and chrome it works great, however on ie it still throws a permission denied error.
The function im running inside the iframe
if(gup("command") == "refresh"){
parent.samRefresh();
}
And in the parent frame I have
function samRefresh(){
location.reload(true);
}
Does any one have any ideas? I know that there are some scripts knocking around to do this however I would prefer not to use them if possible.
Thanks in advance for any help you can give me
Try the following:
In iFrame:
window.parent.success_msg(deferred);
On parent page:
window.success_msg = function(dfd) {
console.log("I'm from the parent window");
};
Also make sure you're running localhost rather than viewing your files from your file system.

Categories

Resources