XSS Challenge - 10K Followers Intigriti
25/11/2019
Here's a brief explanation of my solution for the 10K Followers Intigriti's XSS Challenge.
The challenge consisted in finding a XSS
vulnerability on the following code which was hosted on https://challenge.intigriti.io/
.
<script> const whitelist = ['intigriti.com','intigriti.io']; var url = new URL(location.hash.substr(1)); if(whitelist.indexOf(url.hostname) > -1){ document.write("Redirecting you to " + encodeURIComponent(url.href) + "..."); window.setTimeout(function(){ location = location.hash.substr(1); }); } else{ document.write(url.hostname + " is not a valid domain.") } </script>
What this code should do is just grabbing the hash element of the URL
, check if it's a whitelisted domain, then write it on the document and redirect the user there. If it's not whitelisted, then this is written on the document and nothing else happens.
After not reading the code correctly, I thought the if
statement was just checking if the hostname contained intigriti.com
or intigriti.io
. So my first reaction was to get a domain name that matched.
But I reread the code and saw the hostname had to be one of those exactly, so no domains were needed, only intigriti.com
or intigriti.io
could be used.
Someone could think that the vulnerable part is when document.write
is used because we could directly write something like <script>alert()</script>
on the document, but here there should be no problem in using it, since on line 5
the function encodeURIComponent
is used encoding all special characters, and on line 11
only a hostname could be written, and a hostname can't contain characters like <
.
The only insertion point that we have left is on line 7
where the redirection is performed. Something that everyone may not know is that is possible to use a redirection like this to execute javascript code using a value like location = 'javascript:alert()';
.
Finally, the trick on the code is the double usage of location.hash.substr(1)
on line 3
(before the if
) and on line 7
(after the if
). Between these two instructions is possible to change the hash to bypass the if
statement and this can be done with an iframe
in a script like the following (you have to play with the setTimeout
value to perform the hash change on the exact moment).
<html> <body> <script> var iframe = document.createElement('iframe'); iframe.src = 'https://challenge.intigriti.io/#http://intigriti.com/'; document.body.appendChild(iframe); setTimeout(function(){ iframe.src = 'https://challenge.intigriti.io/#javascript:alert(location.host)'; }, 200); </script> </body> </html>