Block iframe src change through inspect element? - javascript

want to know how to prevent fetching of new data by changing the <iframe> src value in the webpage, through inspect element?
In web page we are showing videos, in <iframe> element. Videos will available to user after purchasing them. All videos are stored in Vimeo, and through Vimeo settings configured in such way that, it will be available only through our domain.
And the problem is,
When a user purchase the video he/she can access the src value of <iframe> and can share with others. And who ever has that url can just go our website and do inspect element and change src value of any <iframe> element in web page, video will be loaded without purchasing.
How to prevent this? Is there any way to make <iframe> to not load the content after page loads? Also if a user want can edit html and put <iframe> element with url. Or is this not the correct approach to implement payed videos in webpage?
I am totally stuck at this point.
Many Many Thanks for all your input.
update:
Can I use google drive for this option? Using google drive api I can dynamically give access to each user account.

It is not possible to prevent this. I'm not sure you can even detect the change from the outside due to cross-origin security, unless Vimeo has an API through cross-window messaging which you could to check the video ID - in this case the best thing you could do is have the page periodically verify the video ID inside the frame.
But even then, for a slightly more advanced "hacker" this would be no problem whatsoever. One could even defeat this whole system just by creating a local webserver which servers an HTML file containing the desired IFrame and setting up an entry in the hosts file which points your domain to 127.0.0.1... Or just use the NoScript extension and disable whatever is checking the video ID on your end.
Bottom line, once you are sending the Vimeo URL over the ether, you lost control over it and that's it. There is nothing you can do about that other than having the video streamed from your own server instead of Vimeo, where you can implement your own access control systems, e.g. creating one-time tokens valid only for this specific user and time, after verifying they rightfully have access to the content.

Your problem is you are trying to take a third party host and create authentication that does not exist.
It wont work all the time, but you could try to set up a setInterval timer that runs a few times a second, if the url changes to an unexpected value you could force the page to redirect to an unauthorized page.
If you go this route I would recommend initially loading the iframe element through javascript, not markup so if the user disables javascript they simply cant view any videos
window.setInterval(function(){
var frame = document.getElementById("frame");
if(frame.src !== expectedSource){
window.location.href = "unauthorized.html" // or something like that
}
}, 300);
// load iframe
window.onload = function(){
var frame = document.createElement("iframe");
document.body.insertBefore(frame, container); // container implies an existin DOM element
frame.src = expectedSource; // you will need some way to get the expected source and load it
}

If you don't want someone to change your iframe's "src", you can make the "src" property 'writable: false', so third party won't be able to change that.
Example:
var element = document.getElementById('iframe');
Object.defineProperty(element, 'src', {
writable: false
});
Also, someone can change src by calling element.setAttribute('src', value), so you can prevent this by overriding the setAttribute method.
Example:
var set = element.setAttribute;
element.setAttribute = function(attr, val) {
//do whatever
//set.call(this, attr, val);
};

Related

Javascript, track iframes redirecting top window

Since there is no way to prevent an iframe from redirecting the top frame besides sandboxing which prevents other features required for viewability tracking I would like to track redirects. Since one site can have more than one iframe, it could be any of these.
Is there any way to track/find out which one (specific iframe) caused the top frame redirect?
Here is a sandbox (use browser console and enable preserve log):
Note the iframe content is usually cross domain. For ease of use its within the sandox.
We can access to the iframe content with somethig like iframe.contentWindow.document but this is possible if we observe Same-origin policy.
Another approach could be setting a Content-Security-Policy header like:
<meta http-equiv="Content-Security-Policy" content="frame-src http://example.com">
This header in the parent page prevents to load sites different to http://example.com in frames, There is also a way to report the refuse behavior sending a post but unfortunately can't be setting with <meta> tag (it's only server side). With this approach we have to perform a white list, so I think maybe it's not useful in this case. But, if the white list is given the first time, is possible to set all sites available, so when the iframe redirect, browser will refuse to load it.
If it's not the case of same-origin and the possibility of performing a white list, then I think the better we can do is calling iframe onunload event, unfortunately this event are going to be fired also when iframe page reloads not only on redirection. I think it's the closest approach. To achieve that, this code works.
var srcs = ["iframe2.html","iframe.html","iframe2.html"];
for (let i = 0; i < srcs.length; i++) {
var iframe = document.createElement('iframe');
iframe.src = srcs[i];
iframe.name = "i"+i;
document.body.appendChild(iframe);
window["i"+i].onunload = function(){console.log("change "+i)}
}
Of course onunload is fired the first time, when all iframes load, so redirections are 2th 3th and so on. But we could exclude that first case.
Here a full example https://codesandbox.io/s/o16yk7mqy , I've created iframe3.html that doesn't refresh neither reload to show clearly the point. Also I've created a simple List of redirect or reload iframes.
UPDATE
As I understand now, what you want is to set iframes with sandbox property and whitelist all what you want but without allow-top-navigation, something like:
<iframe src="iframe.html" sandbox="allow-script allow-forms allow-popups allow-pointer-lock allow-same-origin"></iframe>
This Example doesn't allow allow-top-navigation https://codesandbox.io/s/lpmv6wr6y9
This Example here https://codesandbox.io/s/4x8v1mojq7 allow allow-top-navigation but codesandbox prevents the frame to redirect so if we try https://4x8v1mojq7.codesandbox.io/ that is the url created by codesandbox, we could see the top frame reload.
As I said in comments, at least Chrome 64.0.3282.167, when we delegate all but allow-top-navigation when the iframe attempt to redirect top frame, it throw an exception. The behavior is different in Firefox (at least 58.0.2). Firefox deny top navigation but continues with the code.
So, as conclusion the best approach in my opinion is or a combination of sanbox and onunload or just onunload. Of course, if it could be possible, Content-Security-Policy is the safest and more flexible way. It depends of the implementation. It's almost impossible I think not to involve server side code to perform a perfect solution. There are white list to check, like this API https://developers.google.com/safe-browsing/v4/ and there are black list to check, look at this post https://security.stackexchange.com/questions/32058/looking-for-url-blacklists-of-malicious-websites .
If you have control over all your frames you can implement interaction between frames with postMessage. Flow:
Frame want to execute redirect - it sends a message to parent frame with redirect request.
Parent frame executing redirect and know which frame caused a redirect.
Parent:
window.addEventListener("message", (event) => {
// show message source (your frame)
console.log(event.source);
const message = event.data;
console.log(`Frame ID: ${message.frameId}`);
if(message.messageType === "redirect") {
window.location.href = message.redirectUrl;
}
});
Child frame:
function redirect(url) {
var message = {
messageType: "redirect",
frameId: "frame1"
redirectUrl: url
}
window.parent.postMessage(message, "*");
}
You can show a dialog box before redirecting to another domain/application and then the user can decide - to stay or leave the current application. You can also track the current target (i.e. iframe in your case).
window.onbeforeunload = function (e) {
console.log(e.currentTarget.location.href);
return 'Stop redirection. Show dialog box.';
};
From the individual iframes, can you set a cookie when the redirect happens? Say it happened from iframe1, you may set a cookie like
document.trackFrame = "FrameName=iframe1";
And once the redirect completes, can you try reading the cookie and there by determine which iframe caused the re-direct?

Read iframe redirect (same domain)

I'm working in writing a chrome extension, and as a result I have the peculiar situation of using non-cross domain Iframes, without the ability to alter the page being displayed in the frame.
When a user clicks a certain link, in he iframe, I want to run some JavaScript. The default behavior for clicking that link is to load page targetpage.com. I don't think it's possible, or easy, to read listen for a particular element being clicked inside an iframe
As a workaround, I figure I can check if the iframe reloads, pointing to targetpage.com, and then perform the action.
Note: the action is entirely in the parent page, let's imagine I'm just trying to trigger an alert box.
I know how to trigger JavaScript when an iframe loads. My three questions are:
1) how can I check the url of an iframe?
2) is there a way to check the iframe, url prior to targetpage.com being loaded. Esther than after?
3) is there a better solution?
You could listen to webNavigation.onBeforeNavigate in background page, it fires when a navigation is about to occur, and you could get url and frameId in the callback parameter.
This may not be the best answer because I haven't played around with this much.
Chrome has a webNavigation API that looks to be something which may come in handy for your extension.
However if you want to get the current domain you're on you'd use...
document.domain
If you're in a subdirectory of that domain you can grab that with...
window.location
It also works with an added hash to the url.
If you want the url without the hash you could use document.referrer or if you feel hacky you could do something like...
var str = window.location
var res = str.toString().split(str.hash)
document.body.innerHTML = res

Change url in adress bar when using iframe

I have index page that contains items i want to keep on all the pages. And i have iframe in the middle of the index page, where all the content is shown.
<iframe id="midfr" src="news.html"></iframe>
When clicking on links, content goes to midfr, while website url is always like www.example.com/
Is there a way to have urls like www.example.com/iframe_url/ when going to specified page using iframes? I dont even have a clue on how to do that.
However ive seen some websites that have some constant divs, while main content blinks on visiting links. Although their source code didnt include any iframes..
No, because iframes don't provide any events to the DOM that you can use to change the URL.
Even if your write it as a method to capture and execute the event. You will still not get it. Because it is not allowed.
Iframe won't provide control over any event, untill the code to handle the event is already a part of it.
You can change the Website's URL using History PushState method. But only if you can have an event to do that. Since iframes don't provide you with an event you won't be able to change the URL.

Forcing redraw/repaint of a DOM element in firefox after page load

I've looked through similar threads and tried everything that was suggested there to no avail.
I'm trying to replace an image after the page was loaded by changing it's src attribute once I have a new location. I want to replace the image with a local image.
Directly changing the src attribute via img.src = urlString; or using the setAttribute() method sets the src but doesn't redraw the image in the loaded page. I used window.alert(img.src); to check that the src attribute is really changed.
I've used the following code snippet from here to force a redraw.
var n = document.createTextNode(' ');
var disp = img.style.display;
img.appendChild(n);
img.style.display = 'none';
img.style.display = disp;
n.parentNode.removeChild(n);
Nothing seems to work. Is it because the page is loaded or is it because I am using a local file?
The local file is in %AppData%\temp, could this be a permission problem? The browser console doesn't throw any error. I do not want to refresh the entire page since someone could be typing in a form and they're going to lose their data.
Any input would be appreciated. Thanks.
EDIT : A bit of clarification.
I use an extension to inject a script in every window. Once a window loaded a page I send the images to another script for processing, the script then returns an event to the window with a location to a new file. Once the event is caught, a function is called to change the src attribute of a particular image. I've checked everything, the src is changed but the browser doesn't display the new image.
Another edit :
There doesn't seem to be a permission problem since I can access the file from the address bar using file:///pathtofile/. With external urls (e.g. http://) it seems to work even after page load. How can I make it work with local urls?
Firefox does not allow untrusted pages to load data from file:// URIs in any way. That includes loading images from file:// URIs.
To see why, consider what happens if a page does <img src="file:///dev/tty"> on Linux or Mac, for example. Similar issues exist on some Windows versions if you try to read from file:///c:/con and the like...

Does changing the src attribute of an image stop the image from downloading?

Let's say that I have two accordion tabs. The first one loads hundreds of images and is open when the page loads.
I want to be able to stop the images from downloading if the user clicks on the second accordion tab. Will changing the src attributes of the images via js stop the images from downloading? Or do the requests just continue until completion and not show up on the page?
I have a script that loads the SO logo in exactly 3 seconds that I had made for another question.
http://alexturpin.net/slowimage/slowimage.php
Using it, I tried to reproduce the problem:
var img = new Image();
img.onload = function() {
alert("loaded");
};
img.src ="http://alexturpin.net/slowimage/slowimage.php";
setTimeout(function() {
img.src = "";
}, 1000);
http://jsfiddle.net/Xeon06/RrUvd/1/
From what I gather, in Chrome, the onload doesn't get fired, but the browser keeps on showing a spinner and if I go on the network tab and find my image and check it's content, it's there. So my answer would be no, the image still loads, at least in Chrome.
This is an interesting problem, I suggest you try and test it in as many browsers as possible and write some kind of blog post on it.
Your browser asks for that image with a specific HTTP GET request, as
specificated in HTTP protocol. Once it asks for it, the http server
starts the transfer.
So, it is between the browser (as http client) and the http server.
Since http protocol does not takes into account the option to abort a
transfer, the browser should implement a out-of-standard mechanism to
programmatically abort the connection. But since this is not specified
in any standard, i think you won't find any way to do that with
javascript or any client side code.
You can try window.stop() to stop all requests, but not individual
ones.
If you wanted to stop a single request for a large image, what you
could do is load the image into a document within a hidden IFRAME. The
onload event of the IFRAME can be used to load the image into the main
document, by which time it ought to be cached (presuming you have the
caching directives configured to do so).
If the image is taking too long, then you can access the IFRAME's
contentWindow and issue a stop command to that.
You need to have as many IFRAME elements as there are images that can
be requested simultaneously.
Taken directly from here & here.
Not sure if it will, just like the other comments. But I can suggest am approach that will work well. Assuming not all the images are visible, just set the right src attribute when they become visible.
So default the url to myGray.gif when it is not visible and set it to myImage.jpg when it does come into view.
When you close the current accordion, you can set the image source back to your lightweight gif again. (this prevents a bug related with gc on some versions of the ipad).

Categories