Intigriti 2nd XSS Challenge Writeup


Intigriti 2nd XSS Challenge Writeup
Hey there,

Intigriti hosted their 2nd XSS challenge to celebrate 5k followers. It is an interesting challenge but easier then the previous one. This is challenge is basically a DOM Based XSS.

Original Tweet:
So let's get started by understanding the code.
Lines 1 to 4: It just checks the fragment identifier, if it is empty it just add some string. By looking at the string we can say that its base64, so decoding the string "aW50aWdyaXRpLWNoYWxsZW5nZQ==" gives us intigriti-challenge.

Lines 10 to 23: Basically 10th line gets the fragment identifier by removing the #. At 11th line XMLHttpRequest is initialized, then script assigns a function which only executes if readystate == 4 and status == 200. If it happens, then FileReader is used to read the response and if file reader finishes reading then onloadend funcion will execute which writes the html tag <a> with base64 decoded fragment identifier in the alternate text and FileReader result to the src of an image tag.(Keep an eye at this lines.)
Line 24 to 26: GET request to fragment identifier which is b64img. Therefore, the request will be
https://challenge.intigriti.io/2/#aW50aWdyaXRpLWNoYWxsZW5nZQ==

Two main observations:

1) Fragment identifier must be a valid URL to get the http response 200.
2) And also fragment identifier must be a base64 encoded, because atob(b64img) javascript function is performed for the value of alt attribute in hyperlink tag.


Exploration

Initially I tried to find the other resources in the challenge server to exploit, but it is the waste of time.

Then I tried giving external URLS like https://challenge.intigriti.io/2/#https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png, it doesn't work because of CORS policy.




Ok wait! Can't we just simply bypass this by the server which accepts Cross Origin requests? Ya, we can so let's just spin up a server with index.php file having Access-Control-Allow-Origin: * header in it.
Let's access https://challenge.intigriti.io/2/#http://127.0.0.1/index.php. Wait What?
Connection refused, after some time I found that it is because of we are using https for the challenge server, so browser loads the localhost server using the same https scheme and I don't have certificates for that.
Then I tried loading the challenge server on http, then boom it worked fortunately. http://challenge.intigriti.io/2/#http://127.0.0.1/index.php.

Ya, we can successfully reach to atob javascript function, we got the below error because our http://127.0.0.1/index.php is has the characters like .,: which are not in base64 encoding.


Finding a valid url

Getting rid of http: scheme: After doing some google search I found that we can request  http://challenge.intigriti.io/2/#//127.0.0.1/index.php. without http:, //url we can access any URL without scheme and it is called network reference path.

Getting rid of dots: This can be easily done because we can represent ip in the form of decimal, hexadecimal and octal so our //127.0.0.1 becomes //2130706433. If we are testing in the localhost, we can replace //127.0.0.1 with //localhost

Getting rid of .php: To do this what we can do is, we can write a apache server configuration file to resolve .php file for extensionless php urls. So we can simply get rid of .php. Now our url becomes
//2130706433/index

We found a valid url, now it's time for the payload.

We just have to close the a tag using alt attribute and then injecting the javascript code.
Now our payload will be "><script>"Great" + document.domain</script> and encode it using base64 which becomes Ij4gPHNjcmlwdD4gYWxlcnQoIkdyZWF0ICIrZG9jdW1lbnQuZG9tYWluKTs8L3NjcmlwdD4K.
Then we just have to rename our index.php with Ij4gPHNjcmlwdD4gYWxlcnQoIkdyZWF0ICIrZG9jdW1lbnQuZG9tYWluKTs8L3NjcmlwdD4K.php. 

Final URL : http://challenge.intigriti.io/2/#//2130706433/Ij4gPHNjcmlwdD4gYWxlcnQoIkdyZWF0ICIrZG9jdW1lbnQuZG9tYWluKTs8L3NjcmlwdD4K


And finally we can see the pop up. :)





Comments