Few hours ago intigirit posted their third XSS challenge, the solution of the challenge is a little different than your typical XSS challenges.

In this write up I will try to walk you through both my failed and successful attempts at solving this challenge to give you about how you can approach such challenges.

The following were the instructions for the challenge:

Failed Attempts

Here's the code snippet that was used.

<body>
  <img src="/www3/instructions.png"/>
  <script>
  document.body.append(document.cookie);
  var source = new XMLSerializer().serializeToString(document);
  document.body.innerHTML = decodeURIComponent(source);
  </script>
</body>

As you can see above there doesn't seem like any user input is passed to the code, my first attempt was reading the XMLSerializer().serialize function documentation to see if somehow it can be influenced by user input, however, this was not possible, I did the same with the decodeURIComponent function, I knew that most likely those two functions doesn't accept user input but I like to check the documentation to be sure I didn't miss anything.

My second attempt was trying to check the URL and see if I can pass a parameter or fragment identifier (value after #) that can somehow affect the page or change it's behavior, I was unsuccessful, however, I noticed something interesting the page will be served not matter what you append to the URL, the link for the challenge was https://challenge.intigriti.io/3/, However adding anything to that URL also works for example https://challenge.intigriti.io/3/blahblahblah is still going to work.

My next attempts was after I saw a hint from integrity that says Go Local and another hint that gave it away which was "This page says" instead of "http://challenge.intigriti.io says" this meant that the vulnerability is triggering from a local file not online domain so somehow that user has to download the file.

The next thing I thought about was if I can make a local html file read the data from downloaded challenge file by embedding it in an iframe and then read the file contents, I was pretty sure that this is not going to work given that chrome is preventing this to protect against file stealing using local HTML files but I decided to try may be there's something I didn't know about, again this was a failed attempt.

Successful Attempt

At that point I was a little lost and I didn't know what else to do, so I decided to download the challenge file locally and play around with it, I looked at the source code and I saw this:

Once I saw that, it was done, I knew how to solve this, as you can see the URL is added to the page as a comment which is URL encoded, and the code calls `decodeURIComponent` on the entire page content after appending the cookie we need to steal (see the Javascript code above), we also knew before, that if we append anything to the URL it will load the page normally, so I decided to try loading the page using the following URL and save it to see if this will trigger XSS.

https://challenge.intigriti.io/3/--><script>alert(document.body.innerText);</script><!--.html

I saved the page locally and opened it but the alert didn't trigger, I inspected the source and this is what I saw:

As you can see the script was injected to the page but it didn't trigger, that makes sense given that if you look to the Javascript, you will find that it was injected using `innerHTML`, so instead I used an image tag so the next URL I tested was

https://challenge.intigriti.io/3/--><img%20src=x%20onerror="alert(document.body.innerText);"><!--.html

And this time it worked like a charm:

The payload works in chrome and also in Opera as you can see above.

That was it for now, if you like this write up and want to see more you can poke around in this blog, and you can follow me on twitter for any new ones or if you like you can subscribe for mail notifications below.