In this blog post I will describe how to solve (most of) the stages in the XSS (cross-site scripting) wargame XSS Challenges at http://xss-quiz.int21h.jp/. The only tool I will use is the trusty Firefox.
The server will in its response output the search term into the HTML page. Simply post
and we will finish stage #1.
This time the server won’t put the search term directly into the page. Instead it will be inserted into the input’s value attribute. Therefore we will need to post
to first close the input element.
The server is now properly escaping tags (
<) from the text field.
Right-click in the form and select Inspect Element from the context menu to
show Firefox’s Inspector tool. Find the hidden input field with the name
The default value for this field is
hackme. In the response from submitting
the form to the server this field’s submitted value will be kept. What we want
to do is to submit
to the server, since that will break out from the input field and insert the
script into the page. However, trying to insert that into the input field’s
value attribute with Firefox’s Inspector tool won’t work, because of the
character at the beginning. Instead, insert
into the attribute’s value field (with the
" character escaped to
Escaping ASCII characters can easily be done through this character encoding
The input field’s max length limit is just an artificial limit set in the HTML
and nothing that is enforced on the server-side. Simply increase
something larger than 15 using Firefox’s DOM Inspector tool and submit
On this stage the tags
< are properly escaped on the server to
<. But the rest of the characters aren’t. By submitting
the input’s value attribute will in the response be filled with
123. But the
element will also have an additional attribute that will show the alert window
when hovering the mouse cursor over the field.
The server is now also escaping quotation marks, like
they missed to put quotes characters around the input’s
value, meaning that we still easily can add an additional attribute to the
element. By posting
a will be the field’s value and the additional element attribute will be
onmouseover. This works because it’s not a requirement to put quotes around
an attribute value in HTML.
Christian Heilmann is ranting on these
Solving this stage won’t work in any modern browser since it’s dependent on support for UTF-7. The XSS attack is described on OWASP’s wiki site. Support for UTF-7 was completely removed from Firefox several years ago (per HTML5 spec).
To cheat/skip this stage, open Firefox’s Web Console and execute
alert(document.domain);. This will show the alert which will trigger the
Try to submit
adomainbdomain123 and you will see that
ab123 is returned.
It’s obvious that the server is removing any instance of the word
Start with converting
alert(document.domain); to Base64 with the Character
Encoding Calculator we previously used. Via
the Stack Overflow question Base64 encoding and decoding in client-side
browsers have a global function galled
atob() to decode Base64 strings, read
more on Mozilla Developer
The result that we will submit is:
Since the words
on aren’t allowed, we have to think
as Base64 and make it execute as an iframe src. From the Stack Overflow
question Is it possible to “fake” the src attribute of an
iframe? we can read that it’s
possible to do:
<iframe src="data:text/html;base64, .... base64 encoded HTML data ....">
Read more about data URIs on Mozilla Developer Network. The HTML data we want to use is:
parent. is needed because we want the alert to execute in the context of the
parent’s window. Encoding it as Base64 with the Character Encoding
Calculator results in:
The code that we will then put into the search box to finish the level is:
This is yet another level that doesn’t seem to work, at least not in a modern version of Firefox. According to this thread a working solution should be:
` should work as a substitute for
/ should work as a delimiter.
suggests that this is a working soultion:
However, neither work for me, so I can only assume that this XSS attack doesn’t work any longer. At the first stage of the game it’s even written that some stages only works in IE, and perhaps this is one of them.
To skip the stage, execute
alert(document.domain); in Firefox’s console.
I assume this is also something thas has been fixed.
Stage #15 & Stage #16
document.write(), but I can’t find anything that works.
This stage’s vulnerability is the same one that Twitter once had, read more in the blog post A Twitter DomXss, a wrong fix and something more. However, appending
to the URL doesn’t work for me. I’m only redirected to
For further reading, OWASP has a really good article on DOM Based XSS.
The first ~11 stages were really fun as problem solving challenges. The latter ones were a little wonky, I guess it’s because this wargame has some years on its neck.
If you have any tips, suggestion on better or alternative, interesting XSS code, or solutions to the stages I didn’t manage to solve, please leave a comment below.