Welcome to Code Couch

Enabling cross-site scripting XSS via an iframe

Posted by at 1:24pm on October 19, 2008.

The scenario is relatively common – you have a page that contains an iframe pointing to some content hosted on another domain. Nothing wrong with this – iframes were designed with this in mind! The following diagram shows the sort of setup we are talking about.

Diagram showing an iframe within a web page

Now you want to click a link within the iframe content and have that perform some action on the parent page (maybe you want to submit a form on the parent page, maybe you want to adjust the height of the iframe on the parent page). And you start getting frustrated because the browser won’t let you access all your JavaScript functions/properties on another domain.

Communication from an iframe that has content from a domain other than the one the iframe is contained within is a constant source of frustration – as browsers prevent this kind of activity due to built-in security policies. The solution is actually relatively painless requiring the addition of an iframe (see the following diagram).

Diagram showing page structure for XSS via an iframe

Real world example

You can see a working example of this over at Sky Movies where the iframe is resized as the content within the iframe changes. This is being controlled from within the iframe.

Why do we need to implement a solution like this in the first place?

Because whilst the main page at movies.sky.com can set the height of the iframe, it cannot get the height of the iframe content… and the iframe document can get its height but it can’t set the height of its enclosing iframe.

An explanation of each component of the solution

Using the following example pages, we can create a demonstration of this technique. Following is the source of the main page (marked as [1] in the figure above) which contains the iframe and the function that will be used to resize the iframe.

<html>
<head>
	<title>Page hosted on example.com</title>
	<script type="text/javascript">
	function resizeIframeHeight(nHeight) {
		var iframe = document.getElementById('mainIframe');
		iframe.setAttribute('height', nHeight);
	}
	</script>
</head>
 
<body>
	<h1>This page is hosted on the example.com domain</h1>
	<p>The iframe below is hosted on the example.org domain</p>
	<iframe id="mainIframe" width="400" height="200" src="http://example.org/iframedDocument.html">Iframes not supported.</iframe>
</body>
</html>

Following is the source of the iframe page (marked as [2] in the figure above) which contains the extra iframe and some javascript that allows this technique to work.

<html>
<head>
	<title>Page hosted on example.org</title>
	<script type="text/javascript">
	function updateIframeHeight() {
		var iframe = document.getElementById('hiddenIframe');
		var newHeight = parseInt(document.body.offsetHeight,10) + 10;
		iframe.src = 'http://example.com/xssEnabler.html?height=' + newHeight;
	}
	</script>
</head>
 
<body onload="updateIframeHeight()">
	<h1>This page is hosted on the example.org domain</h1>
	<p>The iframe below is hosted on the example.com domain (and be styled to be hidden)</p>
	<iframe id="hiddenIframe" width="100" height="100" src="http://example.com/xssEnabler.html">Iframes not supported.</iframe>
</body>
</html>

The final source file resides on the original domain (marked as [3] in the figure above) and contains some javascript to strip out the height parameter and then pass this on to the function on the main page that resizes the iframe. It is referred to in the code above, as the content of the file at http://example.org/xssEnabler.html – and whilst it is saved as a .html file, it contains just the code you see below.

<script type="text/javascript">
	function getFirstParamFromLocation() {
		var pair = window.location.search.substring(1);
		var parts = pair.split('=');
		return parts[1];
	}
	var nHeight = getFirstParamFromLocation();
	try {
		window.top.resizeIframeHeight(height);
	} catch(e) {};
</script>

Obviously you would not be using example.com and example.org for your solution, they are used merely to identify the different domains you would use for each file.

Post to Twitter

Tags: , , ,

Comments

There are 2 responses to this post.

  1. thank you! this is super awesome. i have integrated this technology before (facebook connect) but never fully understood what was happening. this example was super clear and super easy. a first step to allowing any 3rd party website to pass back information you need. awesome!!!
  2. Thanks much. This is a great example - concise and well explained. I borrowed from it extensively to implement an xss ajax requestor.

Leave a reply

Comments are closed for this post.