Lab: Client-side prototype pollution via flawed sanitization
This lab is vulnerable to DOM XSS via client-side prototype pollution. Although the developers have implemented measures to prevent prototype pollution, these can be easily bypassed.
To solve the lab:
Find a source that you can use to add arbitrary properties to the global
Combine these to call
Find a prototype pollution source
In your browser, try polluting
Object.prototypeby injecting an arbitrary property via the query string:
Open the browser DevTools panel and go to the Console tab.
Study the properties of the returned object and observe that your injected
fooproperty has not been added.
Try alternative prototype pollution vectors. For example:
Observe that in each instance,
Object.prototypeis not modified.
sanitizeKey()function defined in
searchLoggerFiltered.jsto strip potentially dangerous property keys based on a blocklist. However, it does not apply this filter recursively.
Back in the URL, try injecting one of the blocked keys in such a way that the dangerous key remains following the sanitization process. For example:
/?__pro__proto__to__[foo]=bar /?__pro__proto__to__.foo=bar /?constconstructorructor.[protoprototypetype][foo]=bar /?constconstructorructor.protoprototypetype.foo=bar
In the console, enter
Object.prototypeagain. Notice that it now has its own
fooproperty with the value
bar. You've successfully found a prototype pollution source and bypassed the website's key sanitization.
Identify a gadget
searchLogger.jsdynamically appends a script to the DOM using the
transport_urlproperty if present.
Notice that no
transport_urlproperty is set for the
configobject. This is a potential gadget.
Craft an exploit
Using the prototype pollution source you identified earlier, try injecting an arbitrary
In the browser DevTools panel, go to the Elements tab and study the HTML content of the page. Observe that a <script> element has been rendered on the page, with the
Modify the payload in the URL to inject an XSS proof-of-concept. For example, you can use a
data:URL as follows:
Observe that the
alert(1)is called and the lab is solved.