prompt.ml XSS Summary – Part 1

Here are my solutions for @filedescriptor’s prompt(1) XSS challenges.

Like Erling Ellingsen’s alert(1) XSS challenges, these challenges are very interesting, and sometimes even frustrating 🙂
(you see can a great write up about that challenge by Alvaro Muñoz here)

The purpose of this post is to explain my solutions for this challenge, and perhaps get feedback for solutions with a smaller payload.

Of course, much of the fun is to solve these challenges by yourself.. so please don’t read before you actually try to solve them alone 🙂

In this post I will cover levels 0 to 8. in the next post I hope cover the rest..

Level 0

level_0

no escaping, so the quickest solution i found for all browsers was to use <body onload=”prompt(1)”>

level_0_25

in IE, we can also use the onresize event for <input:

level_0_20_ie

Level 1

level_1

Also here, we open a body tag, and exploit the closing > of </article> to close it:

level_1_23

Level 2

level_2

Here stuff got a little more complicated 🙂

The escape function seriously disallows equal signs and open parenthesis.

If only the parenthesis sign was disabled, we could have used this nice XSS technique described by Gareth Heyes (http://www.thespanner.co.uk/2012/05/01/xss-technique-without-parentheses/)

<script>onerror=eval;throw’=prompt\x281\x29′;</script>

Unfortunately, also the equals sign for “onerror=eval;” is not allowed, so we need another vector

the solution i found was to inject the xss using  a <svg> tag:

level_2_35

here is a great explanation for why it works:

level_2_explain

source: http://security.stackexchange.com/questions/36701/why-does-this-xss-vector-work-in-svg-but-not-in-html

more about svg xss is in mario’s presentation here:

https://www.owasp.org/images/0/03/Mario_Heiderich_OWASP_Sweden_The_image_that_called_me.pdf

 

Level 3

level_3

in this level we need to break html comments, without using anything containing “->”

here again an insight from mario led to the solution:

level_3_explain

(I actually found the reference to this tweet in a great post by Jon Passki:

https://communities.coverity.com/blogs/security/2012/11/16/did-i-do-that-html-5-js-escapers-3)

So, the solution looks like this:

level_3_26

Level 4

level_4

This is a very nice level.

Basically, the fault of the escape function here, is that it calls decodeURIComponent before checking that the script’s src url matches (https?:)//prompt.ml/

So.. this means that we can enter %2f instead of the trailing / – in order to break the format of a legitimate url.

Now the url is broken, we can convince the browser that the prompt.ml%2f is actually a http basic auth username, that we are passing to a different domain

(i.e. http://user:password@example.com )

If we type //prompt.ml%2f@pmt1.ml it will actually load the content of “pmt1.ml”;

level_4_22

Level 5

level_5

here the escape function allows us to pass a quote to the input tag, so we can create new attributes.

it tries to clear all of the onXXXX= events, but it fails because the regex doesn’t handle multi-line input. so we can insert a new line before the equals sign.

now, we could have used the autofocus vector: <input onfocus=”prompt(1)” autofocus>, but also anything containing “focus” is replaced.

The remaining vectors are to use the onresize event for Internet Explorer:

level_5_21_ie

In other browsers, we can override the type of the input to “image” and then use its “onerror” event:

level_5_35

 

Level 6

level_6

In this level, the javascript tries to prevent form submission, if the form’s action contains “javascript”.

the fault here, is that we are allowed to create our own inputs in the form.

so if we create an input named “action”, then checking document.forms[0].action will lead to our new input field instead to the actual form’s action attribute:

level_6_33

 

Level 7

level_7

this is a nice level, where basically we need to build our xss in segments of 12 chars or less

the trick is to use the first segment to close the <p> tag and start our own tag (in my case <body )

then, we open an attribute to contain the “junk” that will be placed between the first and second segments.

in the second segment, we close our “junk” attribute, and open our event (“on load”), then we use a js comment (/*) to contain the “junk” that will be placed between the second and third segments

in the third segment we close the js comment, and call prompt(1)

level_7_explain

level_7_35

 

 

Level 8

level_8

The first challenge here is to break js single line comments.

the escape function does filter out \r and \n, but there are other chars that can break a new line in javascript:

* \u2028 Line Separator
* \u2029 Paragraph Separator

so if we inject \u2028, the output will be:

<script>
// console.log(”
prompt(1)”);
</script>

now the next challenge is to get rid of the trailing “);

it would have been simple if we could use // ot </script>, but / and < are not allowed.

according to http://javascript.spec.whatwg.org/#comment-syntax , we can use –> as a js comment too

so, we go down another line use the closing html comment –>

<script>
// console.log(”
prompt(1)
–>”);
</script>

the easiest way for me to insert \u2028 to the input box was via the console line:

document.getElementById(“input”).value=”\u2028prompt(1)\u2028–>”;

level_8_explain

Then, i just put 1 inside prompt():

level_8_14


Hope you had fun reading this post. see you in the next part 🙂

Please share your thoughts comments, and once again, thanks to @filedescriptor on this great challenge 🙂

2 Comments

Leave a Comment.