is it possible for javascript inside an iFrame to update the URL (hash) of the parent page (and retrieve it)
Does it have any permissions?
To further explain, I have no hosting for this domain, I can only set up an Iframe. I also cannot use a DNS config to get that page to display because of limitations of my hoster.
I also cannot transfer the domain to them to make that work because my clients wants to keep control of the domain.
Thank you for your help!
If the <iframe> page is within the same domain, probably yes. Otherwise you don't get access to the parent page due to cross-domain restrictions.
You can change the URL of the parent page though:
top.location.href = 'http://www.example.com';
due to security constraints you will not be able to access properties of the parent window IF the domain,port or protocol is different than the one in the iframe.
To be short, the answer is NO.
Your script works only inside the context of that iframe.
If you try for example,
var loc = document.location;
you will see what I mean.
One solution is that when you give the other side your iframe, you should add a script in witch you can do whatever you want, because it runs on their domain.
Maybe dynamically create the source of your iframe and stuff.
Related
I am trying to access data of the html document(contains a table) that I am opening in iframe.
I want to access table data.
//#we is id of a <td> #iframe is id of iframe
var q=$('#iframe').find('#we').html();
document.write(q);
But when i use this i always get a null value.help.
Make sure that the iframe is on the same domain, otherwise you can't get access to its internals. That would be cross-site scripting.
None of the browsers would allowing accessing iframe which is from a different domain than your site. It is a serious security breach. Thus if you are loading iframe from different domain, no matter what you do, you can't access it.
You might not like the answer, but it is the fact.
If your iframe is in fact on the same domain - you can use the following.
var q = $('#iframe').contents().find('#we').html();
Please try this:
var body = $('#iframe').contents().find('body');
or this can also be helpful:
$(editFrame).contents().find("html").html();
That should return all the html in the iframe for you. Or you can use "body" or "head" instead of "html" to get those sections too.
I have an iframe that contains a https:// login page, and I have some JavaScript that applies CSS styles to the iframe on the parent window - this parent window being http://. The protocols don't match, and although I know this is to do with the cross domain issue, I can't figure out how it is possible to set both iframe and parent window to use the same protocol without affecting security.
Any help would be appreciated, and code can be posted if required.
Thanks
Since it's different scheme , you can't access it directly.
But it all depends on what you want to do :
You can use : postMessage , hash period check , create cross proxy iframe which has access to parent.parent
You can also use window.name ( but this will reload the other page).
You should tell us what you ACTUALLY want to do ( after you access the page)
I am attempting to share data across subdomains using Safari. I would like to use an HTML5 database (specifically localStorage as my data is nothing but key-value pairs).
However, it seems as though data stored to example.com can not be accessed from sub.example.com (or vice versa). Is there any way to share a single database in this situation?
Update 2016
This library from Zendesk worked for me.
Sample:
Hub
// Config s.t. subdomains can get, but only the root domain can set and del
CrossStorageHub.init([
{origin: /\.example.com$/, allow: ['get']},
{origin: /:\/\/(www\.)?example.com$/, allow: ['get', 'set', 'del']}
]);
Note the $ for matching the end of the string. The regular expression in the above example will match origins such as valid.example.com, but not invalid.example.com.malicious.com.
Client
var storage = new CrossStorageClient('https://store.example.com/hub.html');
storage.onConnect().then(function() {
return storage.set('newKey', 'foobar');
}).then(function() {
return storage.get('existingKey', 'newKey');
}).then(function(res) {
console.log(res.length); // 2
}).catch(function(err) {
// Handle error
});
Check https://stackoverflow.com/a/39788742/5064633
There is simple way to use cross-domain anything, just create simple page that will be included as proxy iframe hosted on domain you try to access, send PostMessage to that iframe and inside iframe you do your LocalStorage database manipulation. Here is a link to article that do this with lcoalStorage. And here is demo that send message to different page in subdomain check the source code, it use iframe and PostMessage.
EDIT: New version of sysend.js library (used by above demo) use BroadcastChannel if browser support it, but still it require Iframe. Recent version also simplify using of Cross-Origin messages, you have html of the iframe in repo, that you can use (or you can use simple html file with single script tag with the lib) and in parent you just need to call one function sysend.proxy('https://example.com'); where example.com need to have proxy.html file (you can also use your own filename and different path).
Google Chrome blocks localStoage access from an iFrame in another domain by default,unless 3rd party cookie is enabled and so does Safari on iPhone...the only solution seems to be opening the parent domain on a different domain and then sending to to the Child via window.postMessage but looks ugly and shifty on phones...
Yes. This is how:
For sharing between subdomains of a given superdomain (e.g. foo.example.com vs bar.example.com vs example.com), there's a technique you can use in that situation. It can be applied to localStorage, IndexedDB, SharedWorker, BroadcastChannel, etc, all of which offer shared functionality between same-origin pages, but for some reason don't respect any modification to document.domain that would let them use the superdomain as their origin directly.
NOTE: This technique depends on setting document.domain to allow direct communication between iframes on different subdomains. That functionality has now been deprecated. (As of April 2021 it continues to work in all major browsers however. From Chrome v109 the feature will be disabled unless an Origin-Agent-Cluster: ?0 header is also sent.)
NOTE: Be aware that this technique removes the same-origin defences that block malicious script on a subdomain from affecting the main-domain window, or visa versa, potentially broadening the attack surface for XSS attacks. There are other security implications for shared hosting as well - see the MDN document.domain page for details.
(1) Pick one "main" domain to for the data to belong to: i.e. either https://foo.example.com or https://bar.example.com or https://example.com will hold your localStorage data. Let's say you pick https://example.com.
(2) Use localStorage normally for that chosen domain's pages.
(3) On all other https://*.example.com pages (the other domains), use JavaScript to set document.domain = "example.com"; (always the superdomain). Then also create a hidden <iframe>, and navigate it to some page on the chosen https://example.com domain (It doesn't matter what page, as long as you can insert a very little snippet of JavaScript on there. If you're creating the site, just make an empty page specifically for this purpose. If you're writing an extension or a Greasemonkey-style userscript and so don't have any control over pages on the example.com server, just pick the most lightweight page you can find and insert your script into it. Some kind of "not found" page would probably be fine).
(4) The script on the hidden iframe page need only (a) set document.domain = "example.com";, and (b) notify the parent window when this is done. After that, the parent window can access the iframe window and all its objects without restriction! So the minimal iframe page is something like:
<!doctype html>
<html>
<head>
<script>
document.domain = "example.com";
window.parent.iframeReady(); // function defined & called on parent window
</script>
</head>
<body></body>
</html>
If writing a userscript, you might not want to add externally-accessible functions such as iframeReady() to your unsafeWindow, so instead a better way to notify the main window userscript might be to use a custom event:
window.parent.dispatchEvent(new CustomEvent("iframeReady"));
Which you'd detect by adding a listener for the custom "iframeReady" event to your main page's window.
(NOTE: You need to set document.domain = example.com even if the iframe's domain is already example.com: Assigning a value to document.domain implicitly sets the origin's port to null, and both ports must match for the iframe and its parent to be considered same-origin. See the note here: https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin)
(5) Once the hidden iframe has informed its parent window that it's ready, script in the parent window can just use iframe.contentWindow.localStorage, iframe.contentWindow.indexedDB, iframe.contentWindow.BroadcastChannel, iframe.contentWindow.SharedWorker instead of window.localStorage, window.indexedDB, etc. ...and all these objects will be scoped to the chosen https://example.com origin - so they'll have the this same shared origin for all of your pages!
The most awkward part of this technique is that you have to wait for the iframe to load before proceeding. So you can't just blithely start using localStorage in your DOMContentLoaded handler, for example. Also you might want to add some error handling to detect if the hidden iframe fails to load correctly.
Obviously, you should also make sure the hidden iframe is not removed or navigated during the lifetime of your page... OTOH I don't know what the result of that would be, but very likely bad things would happen.
And, a caveat: setting/changing document.domain can be blocked using the Feature-Policy header, in which case this technique will not be usable as described.
However, there is a significantly more-complicated generalization of this technique, that can't be blocked by Feature-Policy, and that also allows entirely unrelated domains to share data, communications, and shared workers (i.e. not just subdomains off a common superdomain). #jcubic already described it in their answer, namely:
The general idea is that, just as above, you create a hidden iframe to provide the correct origin for access; but instead of then just grabbing the iframe window's properties directly, you use script inside the iframe to do all of the work, and you communicate between the iframe and your main window only using postMessage() and addEventListener("message",...).
This works because postMessage() can be used even between different-origin Windows. But it's also significantly more complicated because you have to pass everything through some kind of messaging infrastructure that you create between the iframe and the main window, rather than just using the localStorage, IndexedDB, etc. APIs directly in your main window's code.
Suppose http://a.com/foo contains <iframe src="http://b.com/bar">
Sometimes b.com/bar will break out of its frame: the top-level window will redirect away from a.com/foo into b.com/bar. I don't know how b.com is doing this.
I thought it wasn't possible for a cross-domain iframe to interfere with the parent unless the parent cooperates via postMessage. Is changing the window location exempt from this?
If that is what's happening, how can a.com prevent this redirect? I control a.com but cannot modify b.com.
If that's not what's happening, how can I find out what b.com is doing to achieve the redirect?
It would be acceptable to force b.com to load itself into a new window, or sabotage its access to the top or parent objects. Other degradations of b.com's behaviour may be acceptable.
Parent can use sandbox attribute on iframe:
http://www.w3schools.com/TAgs/att_iframe_sandbox.asp
Then iframe will no longer be able to redirect parent.
What may be happening is a link inside b.com has the attribute Target='_parent'.
This would make the window/iframe parent update.
If you control b.com - ensure all your targets are _self.
that's called 'frame busting'. Supposedly there are techniques to stop that ( http://seclab.stanford.edu/websec/framebusting/index.php ).
Maybe instead of an iframe you could use ajax or similar to load the frame's content into your page?
An ajax solution could work if I create a.com/proxy.php which will use cURL to fetch b.com.
Pros:
can change or remove any script
can adjust b.com content (preview mode)
can get around cross-domain iframe restrictions
Cons:
cookies/sessions on b.com won't be available
b.com may require scripts to create its content
burden of bandwidth
coding effort to make hrefs work
I have a rather interesting problem. I have a parent page that will create a modal jquery dialog with an iframe contained within the dialog. The iframe will be populated with content from a 3rd party domain. My issue is that I need to create some dialog level javascript that can detect if the content of the iframe loaded successfully and if it hasn't within a 5 second time frame, then to close the dialog and return the user to the parent page.
I have researched numerous solutions and only two are of any true value.
Get the remote site to include a javascript line of document.domain = 'our-domain.com'.
Use a URL Fragment hack, but again I would need the request that the remote site
able to modify the URL by appending '#some_value' to the end of the URL and my dialog window would have to poll the URL until it either sees it or times out.
Are these honestly the only options I have to work with? Is there not a simpler way to just detect this?
I have been researching if there's a way to poll for http response errors, but this still remains confined to the same restrictions.
Any help would be immensely appreciated.
Thanks
The easiest way (if you can get code added to the external sites) is to have them add an invisible iframe pointing to a special html file on your domain. This could then use parent.parent.foo() to notify the original window about the load event.
Listening for the "load" event will only tell you if the window loaded, not what was loaded or if the document is ready for interaction.
Nicholas Zakas has an article about detecting if an iframe loaded: http://www.nczonline.net/blog/2009/09/15/iframes-onload-and-documentdomain/. Basically you have this code snippet:
var iframe = document.createElement("iframe");
iframe.src = "simpleinner.htm";
if (iframe.attachEvent){
iframe.attachEvent("onload", function(){
alert("Local iframe is now loaded.");
});
} else {
iframe.onload = function(){
alert("Local iframe is now loaded.");
};
}
document.body.appendChild(iframe);
I haven't tested it, but I'm pretty sure jQuery should be able to handle it by doing something like $("#iframe").load(function () { alert("Local iframe is now loaded."); });
You could try using postMessage for communication between frames.
This will require the remote site to include some specific JavaScript to post a message to the parent document when it has finished loading.
It's possible to do this with an onload handler on the iframe itself. Unfortunately (surprise!) IE makes it difficult. The only way I could get this to work was to compose HTML for the iframe, then append it to the document with innerHTML. Then I have to poll to see when the iframe appears in the DOM, which varies depending on if the page is loading. Here's a link to the source: http://svn.openlaszlo.org/openlaszlo/trunk/lps/includes/source/iframemanager.js
See create(), __finishCreate() and gotload(). Feel free to take a copy of this and use it yourself!
Regards,
Max Carlson
OpenLaszlo.org
This is how I detected the loading of a Cross-Domain Iframe,
Set a unique id for the iframe ( U may use any sort of identifier, it doesn't matter )
<iframe id="crossDomainIframe" src=""> </iframe>
Set window event listener:
document.getElementById("crossDomainIframe").addEventListener('load',
function actionToPerform(){
//Do your onLoad actions here
}
)
In any case you will need some sort of cooperation from the other domain's server, as you are trying to abuse the Same Origin Policy (SOP)
The first solution document.domain=... won't work if domains are different. It works only for subdomains and ports, as described in the link above.
The only option that allows cross domain communication without polling is JSONP or script injection with a JS function callback. This method is available in all Google APIs and works well.
We've explained on our blog a way to sandbox those calls in an iframe to secure them. While postMessage is better now, the window.name hack has the advantage of working on old browsers.
Ironically, SOP does not prevent you to POST anything to another domain. But you won't be able to read the response.