Server side detection iframe - iframe

Related issues:
Server-side detection that a page is shown inside an IFrame
I find weird that we can't apparently know from the server side if whether the page is loaded through an iframe. Most answers say that it's only detectable from the browser, I just don't get why.
In the browser, we have access to document.referrer which clearly indicates the url we come from. There is something similar on the server side using req.headers.referer.
I just tested it with a local iframe and I got the following results:
referer http://localhost:8888/tests/chatbotIframeIntegration // The page containing the iframe
referer http://localhost:8888/chatbot // The page displayed within an iframe
referer undefined // seems to be undefined sometimes, maybe due to HMR?)
I can definitely detect the url the request comes from. So, if I know what url my app should be running into, I can definitely have some logic that figures out whether I'm calling my server from an external website, can't I?
Also, it's quite weird that the browser uses referrer and the server uses referer (one r)...

I've gained more experience through experimentation, so here is what I've learned so far.
As I thought, we can resolve the referrer through document.referrer (browser) and req.headers.referer (server).
So, it's possible to detect whether the current referrer is different than what's our hosting server, and in this case we know the query comes from an iframe.
It gets trickier when you want to know, from the server side, if a page within your site has been loaded through an iframe within that same site. In such case, there is no way to automatically detect whether we're running the page from an iframe or not.
For instance, if you have an iframe on page /index that loads /page2 page, then you can't know, from the server side if /page2 was loaded from the iframe (on /index) or from navigating to /page2.
And that's why people say there is no way to know, from the server side, if a page was loaded through an iframe. Because it's uncertain.
Now, my actual need was a little different. I needed to know if my /page2 was loaded from another domain that my own (cross domain), and that is fairly simple to know, because the referrer will be different that my own domain, both on the server side and browser side.
It got a bit more complex with my integration tests, because I had a /tests/iframeIntegration page that contains an iframe which loads another page /page2, from the same domain. (relative url)
The point was to test whether the iframe integration worked as expected, and because it was running on the same domain, I couldn't resolve whether I was loading it through an iframe.
For this particular case, I added a /page2?iframe=true in the url. It's the simplest workaround I've found that works universally (browser + server).
Here are a few utility scripts:
import { isBrowser } from '#unly/utils';
import includes from 'lodash.includes';
/**
* Resolves whether the current web page is running as an iframe from another page
*
* Iframes are only detectable on the client-side
* Also, using iframe=true as search parameter forces iframe mode, it's handy when using an iframe from the same domain
* (because same-domain iframes aren't detected when comparing window.parent and window.top since it's the same window)
*
* #return {boolean}
* #see https://stackoverflow.com/a/326076/2391795
*/
export const isRunningInIframe = (): boolean => {
if (isBrowser()) {
try {
return window.self !== window.top || includes(document.location.search, 'iframe=true');
} catch (e) {
return null; // Can't tell
}
} else {
return null; // Can't tell
}
};
/**
* Resolve the iframe's referrer (the url of the website the iframe was created)
*
* Helpful to know which of our customer use our app through an iframe, and analyse usage
* May not always work due to security concerns
*
* #return {string}
* #see https://stackoverflow.com/a/19438406/2391795
*/
export const getIframeReferrer = (): string => {
if (isRunningInIframe()) {
try {
return document.referrer || null;
} catch (e) {
return null;
}
} else {
return null;
}
};

Related

Detect Chrome switch allow-running-insecure-content from a webpage

I have a SSO login page built in ASP.NET where I authenticate users and then pass them onto another system. This other system, for unknown reasons, requires that Chrome be running with the switch --allow-running-insecure-content in order for some external peripheral devices to run with their website.
My customer is wanting to ensure the current Chrome browser instance is running with this flag/switch set, and if not to display an error/warning message.
Is there any way of detecting this within Chrome itself from ASP.NET? Or, perhaps a way to simulate loading a resource that requires the switch to be set, and then detecting if that resource loaded or not?
Yes, there is a way from the client-side to detect whether Chrome is running with --allow-running-insecure-content.
The trick is to add an insecure resource to the web page and then check to see if that resource was loaded using JavaScript. Using its normal security parameters, Chrome will not load insecure resources from a secure context.
Here's some sample code that does this:
HTML:
<!-- When Chrome is run in insecure mode, as desired, this message will be removed -->
<div class="not-insecure-warning">
Your browser is not configured properly. You must access this page with Chrome using <code>--allow-running-insecure-content</code>. Learn more.
</div>
JavaScript:
// Remove `.not-insecure-warning` elements
function removeNotInsecureWarning(){
var warnings = document.getElementsByClassName('not-insecure-warning');
for(var i = 0; i < warnings.length; i++){
var warning = warnings[i];
warning.parentNode.removeChild(warning);
}
}
var insecureScript = document.createElement('script');
// TODO: Replace URL to an empty `.js` file served over HTTP
insecureScript.src = 'http://code.jquery.com/jquery-3.2.1.js';
// If this insecure script loads, then the browser is running in insecure mode, remove the warning
insecureScript.addEventListener('load', removeNotInsecureWarning);
document.body.append(insecureScript);
See this example on JSFiddle. You should see the warning if you're running Chrome normally, but if you open a new window with insecure content allowed, the warning on this page will disappear.
If you need to pass this information to your server-side logic, you can either:
Use AJAX. Send an XMLHttpRequest if the insecure script fails to load using an event listener like insecureScript.addEventListener('error', isSecureSendPOSTRequest);
Use a hidden form input <input name="is_insecure" type="hidden" value="0"> that you can process immediately after the user logs-in. You can toggle the value of this input using the same kind of client-side logic shown above.
I don't know about a direct solution , but a possible solution is that you can open chrome using the shell script in the c# as follows.
class Module1 {
static void Main() {
System.Diagnostics.Process.Start("chrome.exe", "--allow-running-insecure-content");
}
}
As you want to add --allow-running-insecure-content for loading the browser with that flag

open site in iFrame which avoids Frame Busting

I am trying to open some site in iFrame which opens as popup.
Some sites does not allow itself to open in iFrame (Frame Busting).
I have searched for this . i Have got some solution also like
$(window).bind('beforeunload', function (event) {
return 'Custom message.';
});
beforeunload not work for me, as it will run even when navigating within my site
and also I tried
// Event handler to catch execution of the busting script.
window.onbeforeunload = function () { prevent_bust++ };
// Continuously monitor whether busting script has fired.
setInterval(function () {
if (prevent_bust > 0) { // Yes: it has fired.
prevent_bust -= 2; // Avoid further action.
// Get a 'No Content' status which keeps us on the same page.
window.top.location.href = 'http://mysiteurl/#';
}
}, 1);
above is also not working, it will redirect to the url which is being opened in iFrame.
So Is there any solution to open site (having Frame Buster) in IFrame.
Regards,
Sagar Joshi
For IE use this in your frame security="restricted"
<iframe id="frame_id" name="frame_name" security="restricted" src="page.html">
</iframe>
Edit: I was having the same issue but I needed scripts etc to run in my frame so security restricted was not good. Try using sandbox="..."
allow-forms allows form submission
allow-popups allows popups
allow-pointer-lock allows pointer lock
allow-same-origin allows the document to maintain its origin
allow-scripts allows JavaScript execution, and also allows features to trigger automatically
allow-top-navigation allows the document to break out of the frame by navigating the top-level window
Top navigation is what you want to prevent, so leave that out and it will not be allowed. Anything left out will be blocked
ex.
<iframe sandbox="allow-same-origin allow-scripts allow-popups allow-forms" src="http://www.example.com"</iframe>

Can Cross-Origin Resource Sharing headers authorize X-Domain IFRAME access?

Adjusting the height of an IFRAME to match its content page's height can be a real drag when the containing and content pages are not from the same domain.
Do the Cross-Origin Resource Sharing (CORS) headers make it possible for the content page to authorize cross-domain access to its resources and thus allow its containing page to read its height? (or, alternatively, the containing page authorize the content page to announce its height?)
Or is CORS strictly an AJAX thing?
CORS doesn't let you do that, but you can use cross-document messaging to send strings between iframes and their parent windows even on different domains, and use that to communicate.
Most browsers support this although Internet Explorer's way differs from the others'.
Assuming what you want is to have the iframe announce to the parent page its desired height, you could put this in your iframe code (not tested):
var message = {
width: desiredWidth,
height: desiredHeight
};
window.parent.postMessage(JSON.stringify(message),'*');
And this in your containing page:
function onMessage (event) {
if (event.source != theIFrameElement.contentWindow) return;
var message = JSON.parse(event.data);
var desiredHeight = message.height;
var desiredWidth = message.width;
}
if (window.attachEvent)
window.attachEvent('onmessage', onMessage);
else if (window.addEventListener)
window.addEventListener('message', onMessage, false);
The attachEvent is for IE and addEventListener is for everyone else. You might want to check the target origin for security purposes, but that's the general idea.
EDIT: Browser support for Cross-document messaging (—fsb)

using postmessage to refresh iframe's parent document

I have a greasemonkey script that opens an iframe containing a form from a different sub-domain as the parent page.
I would like to refresh the parent page when the iframe refreshes after the form submission
I am at the point where I can execute a function when the iframe refreshes, but I cannot get that function to affect the parent document.
I understand this is due to browser security models, and I have been reading up on using postMessage to communicate between the two windows, but I cannot seem to figure out how to send a reload call to the parent with it.
Any advice on how to do that would be very helpful
thanks
Use:
window.parent.postMessage('Hello Parent Frame!', '*');
Note the '*' indicates "any origin". You should replace this with the target origin if possible.
In your parent frame you need:
window.addEventListener('message', receiveMessage, false);
function receiveMessage(evt)
{
if (evt.origin === 'http://my.iframe.org')
{
alert("got message: "+evt.data);
}
}
Replace "my.iframe.org" with the origin of your iFrame. (You can skip the origin verification, just be very careful what you do with the data you get).

Replacement for window.sessionStorage in Javascript?

I have an application with a launch page that needs to determine what is already opened, so it does not reopen things that are opened already in another new tab. In Firefox, I was able to make this work, by using window.sessionStorage to store the titles of pages that are open, and then use window.opener with the following code to remove the titles from the list.
Gecko Session Storage Info Page
if (window.sessionStorage) {
if (window.sessionStorage.getItem(code)) {
return; // page already open
}
else {
window.sessionStorage.setItem(code, code);
window.open("Sheet.aspx", "_blank");
}
}
And on the pages that are opened:
function signalPageExit() {
if (window.opener.sessionStorage) {
window.opener.sessionStorage.removeItem(
document.getElementById("runcode").childNodes[0].textContent);
}
This doesn't work in IE so I decided to use a cookie strategy, but the cookies were never successfully deleted from code on the dynamically launched pages, and therefore pages couldn't be reopened from the launch page once they had been launched until the cookie expired.
My second attempt was to define my own sessionStorage when it did not exist. That looked like this:
function setStoreItem(name, val) {
this.storage[name] = val;
}
function getStoreItem(name) {
return(this.storage[name]);
}
function removeStoreItem(name) {
this.storage[name] = null;
}
function sesStorage() {
this.storage = new storageData();
this.setItem = setStoreItem;
this.getItem = getStoreItem;
this.removeItem = removeStoreItem;
}
// storage object type declaration
function storageData() {
}
// IE 7 and others
else {
window.sessionStorage = new sesStorage();
window.sessionStorage.setItem(code, code);
window.open("Sheet.aspx", "_blank");
}
But it seems the real session storage is special, this ordinary object of the window did not stay alive across postbacks and therefore when my launch page posted back, the list of created page titles was wiped out.
So now I'm looking for a way to make this work. I have a launch page called scoresheets.aspx that creates dynamic pages based on user requests. These pages share a substantial amount of javascript code that can be modified to make this work.
I don't want to refresh the launched pages when a user tries to reopen them, but if there is some way to detect the titles of opened pages or some other way to use window.opener to communicate with the same persistence that sessionStorage has, I'd be glad to use it.
Eric Garside’s jStore plugin provides a jquery based api to several client side storage engines.
you should go with that cookie strategy and set those cookies to expire when the windows (tab) is closed. that should work across browsers.

Resources