Intigriti XSS Challenge May 2022
Hello guys I am back again. So let’s start talking rn bc I’m tired of everything.
Last updated
Hello guys I am back again. So let’s start talking rn bc I’m tired of everything.
Last updated
There’s always challenge description and yeah let’s access to the given URL.
Hm main page is telling us something. Wait I know, maybe it’s giving us hint for prototype pollution. Let’s do source code analysis.
So I saw there’s somewhere object called pages.
An object is a collection of pairs that contain keys and their corresponding values. So, we can see that it gets the value of the page by the page
parameter. And if the page value is in the pages
object it will show the HTML content on the site. Also there's filterXSS
function. Basically that function filters untrusted HTML content such as event handlers like onerror ("><img src='x' onerror='alert(1)'>) etc. Everything we want to inject malicious, it will basically filter it out. But however maybe we can inject our own attribute inside the pages
object. There are 3 external JS scripts used on the website. These are for jQuery, XSS and a jQuery plugin called query-object. If we take a look at them we will find out that the jQuery query-object plugin is vulnerable to prototype pollution. Now yeah we can confirm prototype pollution. I was right for that hint on main page. Here’s the link: https://github.com/BlackFan/client-side-prototype-pollution/blob/master/pp/jquery-query-object.md.
Prototype pollution is a vulnerability where an attacker is able to modify Object.prototype. Because nearly all objects in JavaScript are instances of Object, a typical object inherits properties (including methods) from Object.prototype. Changing Object.prototype can result in a wide range of issues, sometimes even resulting in RCE (Remote Code Execution).
The most common way to cause prototype pollution is to use an unsafe merge or extend function to recursively copy properties from an untrusted source object.
Btw after some research I found this repo on github called client-side-prototype-pollution. This repo is a collection of libraries which are vulnerable to prototype pollution. There’s some examples of useful script gadgets that can be used to demonstrate the impact.
The PoC for the jQuery query-object prototype pollution is to use the following request parameter:
?__proto__[test]=test
By using
__proto__
we can set our own attribute and a value for it. We can use this to inject HTML into to webpage.
So I injected code and payload works.
So what I did?
I used this page object (‘rootjkqsta’) instead of page number, and It is parsed into HTML. Now we need to bypass this HTML sanitizer.
Here's one quite interesting article about bypassing HTML sanitizer but not via prototype pollution by the way!
And one important blog about bypassing HTML Sanitizer via prototype pollution:
Let's give some examples how is this working
<h1>Injection</h1>lulz<p>lol</p> <i>lool</i><script>alert(1)</script>
In DOM it will become:
<h1>Injection</h1>lulz<p>lol</p> lool
This is example. It depends of web app's validator, in a nutshell it's a whitelist which allows some tags and attributes. Most of modern web app's today have strong whitelists, so it knows to be pretty hard to gain an XSS. HTML Sanitizer has strong whitelist by the way!
Example:
Let's try to insert some malicious JS code into HTML sanitizer:
sanitizeHtml('<img src=x onerror=alert(1)>')
It will sanitize onerror
event attribute and alert()
function. I think you learned how HTML Sanitizer sanitizes malicious chars. But every modern web app has their own whitelist.
But if I pollute the prototype with:
Object.prototype['*'] = ['onerror']
Then onerror
will be a valid attribute to any tag:
sanitizeHtml('<img src=x onerror=alert(1)>')
This is kinda short. Tho take a look at Michał Bentkowski's blog about this. There's everything explained. Now let's comeback to our challenge.
We can try some payload such as (<script>alert(1)</script>) but we won’t get XSS because it is filtered out by the xss module. But we can use prototype pollution to bypass it. The XSS module accepts a second parameter, called options
. It has a prototype called whiteList
which can be polluted. So, all we need to do is to define our own whitelist accepting img
tag with onerror
event handler and src
attribute. We have defined the whitelist, now we can use the XSS payload: <img src=x onerror=alert(document.domain)>
Btw don’t forget to URL encode the payload. This will be our final payload: ?__proto__[whiteList][img][0]=onerror&__proto__[whiteList][img][1]=src&__proto__[x]=<img%20src%3dx%20onerror%3dalert(document.domain)>&page=x
And that is it. We can confirm XSS.
Hope you enjoy reading this writeup, hope you learn something new, take a care and see you in a next one writeup. Peace out.