Some weeks ago, a XSS challenge was launched: the goal was to pop an alert(1) box in latest Google Chrome at that time (version 53). Code was minified (made by just one continuous line) which always brings interesting possibilities to handle input injections. Also, there was a CSP (Content Security Policy) header that didn’t allow external calls.
Among the solutions, this was the longest:
“><iframe src=”/tests/cors/%23/tests/auditor.php?q1=<img/src=x onerror=alert(1)”
Which uses a demo page in the same domain to trigger an alert. Valid, but somewhat pointless since this domain is full of those.
All other solutions are very similar, with almost all of them making use of double reflection tricks to put alert(1) and <script> in a reverse order:
As we can see in the screenshot of source code above, the injection jumps to line 2 (new line, %0A), where the first alert(1) appears. There, this alert(1) is just the value of the input attribute until the “> is found to close the current tag. It then opens a script tag and comment the rest of the line (line 2).
All submitted solutions are, in some way or another, a variation of this 26 chars one. First and second places of this challenge used the same trick to get rid of the new line (URL encoded) to save 2 chars, submitting the solution by POST HTTP method:
<form action=”http://brutelogic.com.br/chall/minified.php” method=”POST” enctype=”multipart/form-data”>
<textarea name=p id=p>“
In this way, the new line is sent without the need of %0A (payload in red). The shortest GET method based solution was provided by third place, with 25 chars:
Which works in a similar way as previous ones, but saving one char by reusing the * from the comments block to also “concatenate” the regex to alert(1).
This challenge was designed to share a curious solution, the intended one. Although not the shortest and probably because of that it was overlooked by participants, it certainly brings a useful trick to use against Chrome’s anti-XSS filter.
As we can see in red in source code, Chrome’s Auditor flags the injection but it’s executed anyway. It worked by the simple assumption that the only thing that doesn’t allow <svg><script>alert(1)// to work alone (before reaching the </script>) is the native <script> tag.
To disable it, we just enclose it by a pair of tags, like <input>. We already have one inside our <svg><script> block, so adding a closing one (</input>), code can run without syntax error. Notice that the greater than sign is turned into # in the </input/ tag but the “>” found a little bit further (in “if(p.length>0)” snippet) make it work properly.
More info can be found below, in the tweet itself (check replies) and in the write-up by one of the winners.
— Matt Austin (@mattaustin) October 6, 2016
It seemed to be a good challenge to practice some XSS filter skills, as pointed out by some participants. It also had some nice prizes provided by sponsors, Hackfest CA, Sucuri and BHaFSec. Stay tuned to my twitter account @brutelogic for the next ones!