EDIT:
Just a quick mention as to the nature of this program. The purpose of this program is for web inventory. Drawing different links and other content into a type of hierarchy. What I'm having trouble with is pulling a list of links from a webpage within an IFrame.
I get the feeling this one is gonna bite me hard. (other posts indicate relevance to xss and domain controls)
I'm just trying something with javascript and Iframes. Basically I have a panel with an IFrame inside that goes to whatever website you want it to. I'm trying to generate a list of links from the webpage within the Iframe. Its strictly read only.
Yet I keep coming up against the permission denied problem.
I understand this is there to stop cross site scripting attacks and the resolution seems to be to set the document domain to the host site.
JavaScript permission denied. How to allow cross domain scripting between trusted domains?
However I dont think this will work if I'm trying to go from site to site.
Heres the code I have so far, pretty simple:
function getFrameLinks()
{
/* You can all ignore this. This is here because there is a frame within a frame. It should have no effect ont he program. Just start reading from 'contentFrameElement'*/
//ignore this
var functionFrameElem = document.getElementById("function-IFrame");
console.log("element by id parent frame ");
console.log(functionFrameElem);
var functionFrameData = functionFrameElem.contentDocument;
console.log("Element data");
console.log(functionFrameData);
//get the content and turn it into a doc
var contentFrameElem = functionFrameData.getElementById("content-Frame")
console.log(contentFrameElem);
var contentFrameData = contentFrameElem.contentDocument;
console.log(contentFrameData);
//get the links
//var contentFrameLinks = contentFrameData.links;
var contentFrameLinks = contentFrameData.getElementsByTagName('a');
Goal: OK so due to this being illegal and very similar to XSS. Perhaps someone could point out a solution as to how to locally store the document. I dont seem to have any problems accessing document.links with internal pages in the frame.
Possibly some sort of temp database of cache. The simpler the solution the better.
If you want to read it just for your self and in your browser, you can write a simple proxy with php in your server. the most simple code:
<?php /* proxy.php */ readfile($_GET['url']); ?>
now set your iframe src to your proxy file:
<iframe src="http://localhost/proxy.php?url=http://www.google.com"
id="function-IFrame"></iframe>
now you can access the iframe content from your (local) server.
if you want set the url with a program remember to encode the url (urlencode in php or encodeURIComponent in js)
Here is a bookmarklet you can run on any page (assuming the links are not in an iframe)
javascript:var x=function(){var lnks=document.links,list=[];for (var i=0,n=lnks.length;i<n;i++) {var href = lnks[i].href; list.push(href)};if (list.length>0) { var w=window.open('','_blank');w.document.write(list.length+' links found<br/><ul><li>'+list.sort().join('</li><li>')+'</ul>');w.document.close()}};void(x());
the other way is for you (on Windows) to save your HTML with extension .HTA
Then you can grab whatever lives in the iFrame
You might be interested in using the YQL (Yahoo Query Language) to retrieve filtered results from remote urls..
example of retrieving all the links from the yahoo.com domain
Related
I have the following situation:
a static site, only html pages
a cookie notice system, with my own cookies, accept and refuse system of cookies setup
Now I need to inject the GA4 script into the head of pages when cookies are accepted, but...
I have already made made that, by appending the script to the head and it is visible on browser, on page reload with inspect elements...and it's working perfect.
When users click on accept cookies, the cookies accept is saved on client's side, and the script is APPENDED to page.
But I need the GA4 script to be somehow INJECTED, to be visible on the source page. Like when I preview the source page in browser to have it there. I don't need it to be injected into the html file itself, but only into the browser.
I did my own research about these days, and now it's killing me, as all I could find was the append way, but that is not injecting it into the source page on browser.
Any advice or guidance would be greatly appreciated.
Note (as I have been asking all the time. I don't want to offend anyone, but that's the best way I can explain where I want to do and what):
the source page I'm talking about is when right click on browser and view source page (there is where I need the GA4 code to be inserted)
and the way I got it to work is when right click > inspect > elements tab - (there i have it now working)
Thank you!
First question would be, why do you want it to be in the actual source code? A common way of inserting these scripts is through a tag-management-solution, which basically follows similar logic as appending scripts to the page (i.e. similar to what you meant by the inspect elements route).
To answer your question;
There is an option to get it into the sourcecode, and that is by checking on the server delivering the HTML whether a user has accepted the cookies, if that is the case deliver the HTML file (or adjust the HTML) to contain the GA4 script, if the user didn't accept: deliver the page without the GA4 script.
Since you mention these are static HTML files, I assume there is no server in place where this kind of logic can be inserted. So the best option is to insert the script afterwards.
Another way would be to insert the tag by default, but disable tracking (haven't tested the below part, also, verify yourself whether in your situation this actually blocks tracking when cookies aren't accepted):
window['ga-disable-GA_MEASUREMENT_ID'] = true;
https://developers.google.com/analytics/devguides/collection/gtagjs/user-opt-out
You could try to add this in your HTML before loading the GA4 tag, similar to something like:
<script>
const gaMeasurementId = 'G-12345678'; //replace with your own MeasurementID
let cookiesDeclined = true; //default to declined cookies
document.cookie.split(';').forEach( (cookie) =>{ //loop through all cookies
const cookie_arr = cookie.split('='); //get key/value pairs for cookies
let name = cookie_arr[0]; //cookiename
let val = cookie_arr[1]; //cookieval
if(name === 'cookieConsent' && val === 'accepted' ){
cookiesDeclined = false; //set the declined status to false when user has accepted the cookies
}
})
window['ga-disable-'+gaMeasurementId] = cookiesDeclined;
//->insert ga4 tag here
</script>
As many of us know there is no way to edit a Cross Domain IFrame due to the Same Origin Policy.
Is there a way around this if we use the Stylish extension etc. locally only?
Take this video being launched inside an iframe for example:
I need to simply add "zoom:2;" onto "#video21588864 iframe figure"
If this is 100% not possible, why am I able to do it successfully in the Inspector window, but not automatically? Is there really ZERO automatic local ways around this using Javascript or something?
There is no way you can access the content inside the <iframe> in a cross-origin fashion. You might be able to if the response includes a CORS header.
Why am I able to do it successfully in the Inspector window
The developer tools is separate from your document. It can do much more things that you cannot possibly do with normal JavaScript in a webpage.
Rationale
There is a reason why you cannot access the content inside an iframe. Consider this, a user was logged into their bank webpage. A token is stored in a cookie to prove that the user is logged in.
Now you include an iframe in your webpage and loads the bank's webpage. Since the cookie contains a valid token, the iframe will show that the user has been logged in.
Wouldn't it be great if you can access the iframe and send yourself some money? Well, this is exactly why it's not allowed, 100% not possible, given that the browser is implemented correctly.
Addendum
I have decided to add this part after seeing that you have mentioned the word locally. Now, I do not know exactly what you are trying to do, but it is possible to manipulate the content inside the iframe if you have an elevated privilege, including:
a userscript
an extension with proper permissions acquired
developer tools
the browser itself
If you merely want to add zoom: 2 to videos from ESPN on your own computer, I would suggest creating a userscript which has a much higher privilege than a normal webpage and much easier to make than an extension.
// ==UserScript==
// #match http://www.espn.com/core/video/iframe*
// ==/UserScript==
document.querySelector("figure").style.zoom = 2;
Save that as myscript.user.js. Open up chrome://extensions and drag that file onto the page. The userscript will have a higher privilege and can access the page.
One way to edit cross-origin domains in an iframe is to load them via the server (PHP) and modify the html by adding a base tag: <base href='http://www.espn.com'/> It's no guarantee that they will let you load all the elements as html and still render the page properly but can work in some cases and is worth the try.
A very simple iframe-loader.php would look like this:
<?php
error_reporting(0);
$url = $_REQUEST['url'];
$html = file_get_contents($url);
$dom = new domDocument;
$dom->strictErrorChecking = false;
$dom->recover = true;
$dom->loadHTML($html);
//Add base tag
$head = $dom->getElementsByTagName('head')->item(0);
$base = $dom->createElement('base');
$base->setAttribute('href',$url);
if ($head->hasChildNodes()) {
$head->insertBefore($base,$head->firstChild);
} else {
$head->appendChild($base);
}
//Print result
echo $dom->saveHTML();
DEMO
Then you load a url by going to /iframe-loader.php?url=http://www.espn.com/core/video/iframe?id=21588864...
Good Luck!
I am planning to create an open source education web app where people can add and edit the content (a bit like Wikipedia).
However I wish to add another feature that allows the user to add their own interactive content using JavaScript. (similar how JSFiddle does it)
What are the security concerns in doing this?
Optional question: How can these issues be overcome?
Yes you could use HTML5 Sandbox to only load user scripts in an IFrame.
You should only host user content from a different domain than your main site. This will prevent any XSS attack if an attacker convinces a user to visit the page directly (outside of the sandbox). e.g. if your site is www.example.com you could use the following code to display the sandboxed IFrame (note .org rather than .com, which is an entirely different domain):
<iframe src="https://www.example.org/show_user_script.aspx?id=123" sandbox="allow-scripts"></iframe>
This will allow scripts, but forms and navigation outside of the IFrame will be prevented. Note that this approach could still risk a user hosting a phishing form to capture credentials. You should make sure that the boundaries between your site and the user content are clear within the user interface. Even though we haven't specified allow-forms, this only prevents a form from being submitted directly, it does not prevent form elements and JavaScript event handlers from sending any data to an external domain.
The HTML5 Security Cheat Sheet guidance on OWASP states this is the purpose of the sandbox:
Use the sandbox attribute of an iframe for untrusted content
You should test whether sandbox is supported first, before rendering the IFrame:
<iframe src="/blank.htm" sandbox="allow-scripts" id="foo"></iframe>
var sandboxSupported = "sandbox" in document.createElement("iframe");
if (sandboxSupported) {
document.getElementById('foo').setAttribute('src', 'https://www.example.org/show_user_script.aspx?id=123');
}
else
{
// Not safe to display IFrame
}
It is safer to do it this way by dynamically changing the src rather than redirecting away if sandboxSupported is false because then the iframe will not accidentally be rendered if the redirect doesn't happen in time.
As a simpler alternative, without the need to check whether the sandbox is supported, you can use the srcdoc IFrame attribute to generate the sandboxed content, making sure that all content is HTML encoded:
e.g.
<html><head></head><body>This could be unsafe</body></html>
would be rendered as
<iframe srcdoc="<html><head></head><body>This could be unsafe</body></html>" sandbox="allow-scripts"></iframe>
Or you could construct a data blob object, being careful to HTML encode again:
<body data-userdoc="<html><head></head><body>This could be unsafe</body></html>">
<script>
var unsafeDoc = new Blob([document.body.dataset.userdoc], {type: 'text/html'});
var iframe = document.createElement('iframe');
iframe.src = window.URL.createObjectURL(unsafeDoc);
iframe.sandbox = 'allow-scripts';
</script>
Of course you could also set the unsafeDoc variable from a JSON data source. It is not recommended to load an HTML file, as this has the same problem of it having to be from an external domain, as the attacker could just entice the user to load that directly.
Also, please don't be tempted to write user content into a script block directly. As shown above, data attributes is the safe way to do this, as long as correct HTML encoding is carried out on the user data as it is output server-side.
In these cases you can leave src as blank.html as older browsers that do not support srcdoc will simply load that URL.
As #Snowburnt touches upon, there is nothing stopping a user script from redirecting a user to a site where a drive-by download occurs, but this approach, assuming a user is up to date on patches, and there are no zero day vulnerabilities, this is a safe approach because it protects its end users and their data on your site via the same origin policy.
One big issue is cross-site scripting where users add code that tells the browser to open and run code from other sites. Say they add something that creates an iFrame or a hidden iFrame pointing to a site and starts downloading malicious code.
There's no simple way around it (thanks to Bergi in the comments) to make sure no elements are created and no ajax calls are made.
I've been a member of sites that provided this functionality, but for those sites I paid for my own space so any vulnerabilities I add are inconveniencing my own clients, in that case it's a little more okay to let that slip by since it's not a security leak for everyone.
One way around this is to create customizable controls for the users to use to add interactivity. The plus is that you control the javascript being added, the minus is that your user base will have to request and then wait for you to create them.
I have an iframe on one of my pages that shows content on an external site (vendor product). All works well except a few links that have target="_main" in them. These links open in a new tab. What I need to do is strip the target attribute from all links within the iframe so all links stay within the iframe rather than opening a new window or tab.
It seems like there should be a simple javascript solution to this.
If I can't get this to work in an iframe then I will be forced to re-create all the content on my site which would be very painful..... to say the least.
Any help???
You need access to the external site's codebase in order to dynamically fix this. What you want to do in the external site's codebase is to check if the sites is within an iframe. If it is within an iframe then run a function to remove all target attributes on links.
// vendors product page
if ( self !== top ){
$('a').removeAttr('target');
} // else do nothing
self !== top is the same as saying if my site isn't the top most window then return true.
Not directly that I am aware of.
However, if you have access to a scripting language (like PHP or ASP) on your site you can read your vendors' page directly from your server, do a find & replace on it & then render that onto your site; either in an iframe or however else you want.
Edit
There are many ways to do this, depending on how much control you have over you PHP config. Have a look at these resources & see if you can figure out what to do. If not I would suggest you start a new question specifically focused on what it is you are struggling with.
http://php.net/manual/en/function.file-get-contents.php With this method you have to be aware of the tip on the page:
A URL can be used as a filename with this function if the fopen wrappers have been enabled. See fopen() for more details on how to specify the filename. See the Supported Protocols and Wrappers for links to information about what abilities the various wrappers have, notes on their usage, and information on any predefined variables they may provide.
http://php.net/manual/en/function.fsockopen.php Again, be aware of the warning & notes.
http://php.net/manual/en/book.curl.php
I personally have written a class that uses fsockopen because it is the most flexible for my needs but usually file_get_contents does the trick because it is the simplest to set up out of the 3 options, if you have the right wrappers configured & you don't need to start working with SSL or funny protocols. I stay away from CURL because you have to install a library in order for it to work. I prefer my code to be portable for standard installs.
Some useful links that might help:
PHP readfile from external server
Possible Example
$vendorUrl = isset( $_REQUEST['vendor'] ) ? $_REQUEST['vendor'] : 'www.default-vendor.com';
$iframeContents = file_get_contents("http://$vendorUrl", false);
exit str_replace( 'target="_main"', '', $iframeContents );
Then you just have point your iframe at whatever page you save this script in on your server & include ?vender=www.vendor-url.com as the query string.
How about giving your own iframe the name _main?
<iframe name="_main" ...
The other links should then open in that iframe too.
Regards, Max
I am trying to get the source page of a webpage on a different domain. I know this is easily done with PHP for example but I would like to do it in Javascript because I am getting results from a page and if I use a server-side language, the original website will block the calls since they come from the same IP. However, if the calls are done on the client side, it is like the user request the results each time (different user, different IP, no original site blocking me). Is there a way to do that (even if not in Javascript but client-side).
To clarify the code I want will be applied to an HTML page so I can get the results, style them, add/delete, etc then display them to the user.
Thank you.
Modern browsers support cross-domain AJAX calls but the target site has to allow them by using special headers in the reply. Apart from that, there is no pure Javascript solution AFAIK.
Could you use an iframe? You wont have direct access to the markup to due to cross-domain restrictions, but you can still display the third-party page to the user...
window.onload = function() {
var i = document.createElement("IFRAME");
i.setAttribute("name", "ID_HERE");
i.setAttribute("id", "ID_HERE");
i.setAttribute("src", "URL_HERE");
i.style.maxHeight = "300px";
i.style.width = "100%";
document.body.appendChild(i);
}
On Windows you can use HTA
An HTA can access anything crossdomain in an iframe for example