Skip to main content

XSS Hacks For Fun And Profit


Sometimes, just sometimes, I want to do something completely ludicrous with my web pages. For instance, just recently I wanted to embed dynamic, externally hosted content in a Blogger page, and I wanted to do it without having internal scroll bars. This meant sizing the iframe hosting the content to precisely fit the content within it, resizing it every time the content changed.

Told you it was ludicrous.

Anyway, I quickly ran into a few problems to do with cross-site scripting. Specifically, when a page is contained in an iframe within a page on a different domain, there are two things you can't do:

  1. It's impossible to size an iframe to its contents from the containing page
  2. It's impossible to size an iframe to its contents from inside the iframe

So how do I do it? Well, I use a mighty XSS hack! Give this a try:

Create a resizing widget

Create a blogger page called 'resize-widget' that contains the following code:

<script type="text/javascript">
<!-- 
      /**
       * This iframe gets load by the first iframe. This one
       * will communicate with the main page telling it to
       * resize the iframe that has content in it. It will
       * get the height from the URL that was used to
       * link to this page, e.g. iframe-resize.html?height=456
       */
        var params = window.location.search.substring( 1 ).split( '&' );
        var height;
        for( var i = 0, l = params.length; i < l; ++i ) {
          var parts = params[i].split( '=' );
          switch( parts[0] ) {
          case 'height':
            height = parseInt( parts[1] );
            break;
          }
        }
        if( typeof( height ) == 'number' ) {
          window.top.updateIFrame( height );
        }
//-->
</script>

What does it do? Not a lot. It pulls the request URL apart, finds a parameter named "height", and then calls a Javascript function on the topmost frame, passing the value of the height parameter as an argument.

Of course, it assumes that it is allowed to call functions on the topmost frame (i.e. it's on the same domain), and that the updateIFrame function exists. But assuming that is true, all is well.

Create the containing page

Next, create a page to contain your iframe to be resized. I will call mine iframe-resize-demo, although of course you can call it anything you like. Put this code in it:

<script type="text/javascript">
<!--
      /**
       * This function must be available on the main outer page.
       * When called with a height it will update the size of the
       * iframe to match that height.
       */
      function updateIFrame( height ) {

        var iframe = document.getElementById( 'myiframe' );
        var sidebar = document.getElementById( 'sidebar-wrapper' );
        iframe.setAttribute( 'height', Math.max(height, sidebar.scrollHeight) );

        var content = document.getElementById( 'content-wrapper' );
        document.body.scrollTop = Math.min(document.body.scrollTop, content.offsetTop);
      }
//-->
</script>

<iframe frameborder="0" height="150px" id="myiframe" scrolling="NO" src="http://my-nested-domain.com" width="100%"></iframe>

Aha! There's that updateIFrame function that takes a height as its parameter! What does it do? It updates the height of the iframe to match the height parameter. Actually it does a little more - it resizes it to the maximum of either the height parameter or the scrollHeight of the Blogger sidebar. It does this to ensure the Blogger template flows properly.

Create the dynamic, externally-hosted content

Of course, the external content can contain anything you like. But put this in it:

<script type="text/javascript">
<!--
/**
 * This function will update the URL on the inner iframe,
 * i.e. the iframe within an iframe.
 */
function resizeThisFrame() {
    var iframe = document.getElementById( 'inneriframe' );
    var wrapper = document.getElementById( 'wrapper' );
    var height = Math.max( document.body.offsetHeight, document.body.scrollHeigh
t );
    iframe.src = 'http://myblog.blogspot.com/p/resize-widget.html?height
='+height;
}
//-->
</script>

<body onload="resizeThisFrame()">
<iframe height="1px" width="1px" id="inneriframe" style="display: none;"></iframe>

What does it do? When the document body loads, it calculates the total height of the document, adds it to the URL of the resize-widget page we created a while back, and loads that URL into the iframe. This sets of a chain of events that culminates with the height parameter calculated here being passed into the updateIFrame function, and the iframe containing the page we've just written being expanded to fit!

Don't you feel dirty now?

Inspiration from Blog What I Made, and modified to work with Blogger.

Comments

Popular posts from this blog

Juniper Network Connect on Mac OS X Snow Leopard

Juniper Network Connect is a very popular VPN client for corporate networks. It bootstraps from a Java applet and has native versions for Windows, Linux and Mac, and works very well. Unfortunately, it seems that Mac OS X 10.5 Leopard and 10.6 Snow Leopard have some issues caused by a dodgy installation program. One common way to make it work is to enable the root user and log in with full admin privileges under OS X and install it that way. This is a sledgehammer approach to a fairly simple problem, opens up security issues, and didn't even work for me. I won't even bother exploring that route in this blog post. There are a couple of other things that can be done to make it work, though. If you upgraded from a previous version of OS X and already had the Network Connect client installed, you may just be suffering a simple permissions issue. These instructions are for Network Connect 6.2.0, but they might well work with other versions with a tweak. From Termin...

Something is afoot - Opera Mini on iPhone

Strange things are afoot. 20 days ago, Opera submitted the iPhone version of Opera Mini , their mobile browser, to the Apple AppStore. 20 days later, it was actually approved, despite previous browser technologies and the like being rejected for "duplicating iPhone functionality". Strange indeed. Having used Opera Mini before on many different devices, both touchscreen and traditional keypad based, I have long appreciated its raw speed, excellent rendering engine and intuitive navigation controls. But can it stand up to Safari on iPhone for browsing excellence? The answer: sort of. The Good Like its predecessors, Opera Mini for iPhone is blazingly fast. Using Opera's own proxies, web content is compressed to within an inch of its life to reduce bandwidth requirements, and the browser itself renders what it downloads so fast that the likes of Safari just can't keep up. Even on a GPRS only connection it is almost as fast as Safari on 3G for largely text based page...

Removing dead tracks from iTunes

On occasion, for one reason or another, iTunes seems to have a link to a file that no longer exists. Your options are then to either hunt for the file manually, one by one, or manually hunt and delete all the dead ones. There is a handy exclamation point icon that will tell you which are broken, but there is no way to filter for these. Fortunately, thanks to a bit of logical jiggery pokery, you can use Smart Playlists and a cunning quirk of iTunes to do it for you. Herein lies a step-by-step guide to finding all those annoying broken links. Step 1 Create a new Smart Playlist with a single Artist Does Not Contains rule. Put some garbage into the search field so it will return every artist. Call this playlist "All Music". Step 2 Create a normal playlist called "Working Music". Step 3 Create a Smart Playlist with 2 rules. These are: Playlist - is - All Music Playlist - is not - Working Music ...