Solution for Intigriti’s August XSS challenge
Heyyy Everyoneee,
In this blog, I will be discussing the solution for the Intigriti’s August XSS challenge.
INTIGRITI on Twitter: "⏰ It's CHALLENGE O'CLOCK!👉 Find the XSS before Sunday August 22nd, 23:59 CET👉 Win €300 in SWAG prizes👉 We'll release a tip on our Discord (Check replies for link) for every 100 likes on this tweet!Thanks @WHOISbinit for the challenge! 👇https://t.co/f631AbNmXf / Twitter"
⏰ It's CHALLENGE O'CLOCK!👉 Find the XSS before Sunday August 22nd, 23:59 CET👉 Win €300 in SWAG prizes👉 We'll release a tip on our Discord (Check replies for link) for every 100 likes on this tweet!Thanks @WHOISbinit for the challenge! 👇https://t.co/f631AbNmXf
This will be a step by step walkthrough how I was able to find the xss vulnerability.
Opening the challenge url, we can see that this endpoint https://challenge-0821.intigriti.io/challenge/cooking.html is loaded in the home page in an iframe.
Under collections you will find 3 urls which are having a base64 encoding string in the recipe parameter.
Here is the url for the collection which says The basic XSS:
Upon opening the above url , you can notice that under Recipe, now it’s not showing undefined like before.
By decoding the base64 encoded string, we now know where these values came from.
I modified the parameter values to a xss payload and then re encoded it to base64 to see if the xss payload works or not. It didn’t work
From the js code (main.js), you can see that these parameter values are passed to innerText (which is a safe approach here)
As it was not possible to do anything from the recipe parameter, I started reading the js code to see where this username unknownUser281 came from.
After reading the code I found that this username is taken from the cookie:
The code first reads the value for the cookie username parameter and then pass on line no 18 to the innerHTML
At this point I thought if we can somehow take control over this cookie parameter we can easily get a xss as the value of the username cookie parameter is passed to innerHTML.
We can verify the same by changing the cookie to a xss payload and here in this screenshot you can see that this actually works:
It’s a self xss for now, now we need to find a way to change it with some another way.
On line no 52 , the decoded value of the recipe parameter is passed to the deparam function.
If you know already about the author of this challenge @WHOISbinit, you are aware that he has shared some great prototype pollution challenges in the past.
In one of his challenges he used the same vulnerable deparampackage.So it became very clear what I had to do next.
For more info regarding this you can read the below blogs:
- Snyk - Prototype Pollution in jquery-deparam
- client-side-prototype-pollution/pp/jquery-deparam.md at master · BlackFan/client-side-prototype-pollution
If you are new to prototype pollution , I recommend watching this two videos:
Now let’s move on to prototype pollution,
At first I started with a basic payload __proto__[test]=test
If this payload works every object will have a new property name test with value test
In this url, I have encoded the payload as if you remember the code from line 52 , that the application first decodes the base64 string then it is used in the deparam function, so in order to make it work we have base64 encoded our payload.
It worked , the test property has been added successfully.
Now we already know about the sink (innerHtml), have a working prototype pollution payload. The only missing thing is a script gadget which will allow us to make modification to the cookie parameter’s value.
Looking for a script gadget…..
When it comes to prototype pollution, this repo is super useful. It contains the list of vulnerable packages with working payloads along with script gadgets in popular js files such as in our case it’s Google analytics:
GitHub - BlackFan/client-side-prototype-pollution: Prototype Pollution and useful Script Gadgets
Along with importing the deparam js file, one more is imported Google Analytics
The above mentioned repo also has a script gadget for the Google analytics.js
?__proto__[cookieName]=COOKIE%3DInjection%3B
Bingo exactly what we were looking for, this will allow us to change the usernamecookie parameter value to a xss payload.
Again first verifying it before adding the xss payload:
__proto__[cookieName]=username%3Dshirley%3B
As it’s perfectly fine we will add the xss payload now:
__proto__[cookieName]=username%3Dshirley%3Cimg%20src%3Dx%20onerror%3Dalert%28document.domain%29%3E%3B
And here we go , we successfully executed the popup:
Thankyou for reading it till the last :)
Sya Everyonee!