Prototype pollution

Prototype Pollution occurs when an attacker manipulates __proto__ (See ECMAScript® 2015 Language Specification), usually by adding a new Prototype onto __proto__. Since __proto__ exists for every Object, and every Objects inherits the Prototypes from their Prototype, this addition is inherited by all the JavaScript Objects through the prototype chain. Detecting these vulnerabilities requires reading and understanding a lot of JavaScript code, which can be time-consuming.

Malicious players can take advantage of the ability to insert properties into existing JavaScript code, and execute either Denial of Service attacks, by triggering JavaScript exceptions, or Remote Code Execution, by injecting malicious code. In short, it is an injection attack that targets JavaScript runtimes.

JavaScript can run on the client-side and server-side of a web application, and prototype pollution vulnerabilities can exist on both sides.

Steps

Client-side prototype pollution (CSPP)

  • Find prototype pollution sources

  • Testing a prototype pollution sources/Try to modify the prototype

  • Find possible prototype pollution gadgets

  • Try the Burpsuite DOM Invader browser extension

Server-side prototype pollution (SSPP)

Prototype pollution sources

Prototype pollution is a vulnerability that occurs when merging an object with a user controlled JSON object. It can also occur as a result of an object generated from query/hash parameters, when the merge operation does not sanitise the keys. This makes it possible to use property keys like __proto__ , by which arbitrary assignments to the Object.prototype (or other global prototypes) can be created. When this happens, it is referred to as a prototype pollution source.

Detecting CSPP with DOM Invader

DOM Invader is a browser-based tool that helps test for DOM XSS vulnerabilities using a variety of sources and sinks, including both web message and prototype pollution vectors. It is available via Burp’s built-in browser, where it comes preinstalled as an extension. When enabled (if the BurpSuite icon is not visible, pin it under the jigsaw first), DOM Invader adds a new tab to the browser’s DevTools panel. To use it for finding CSPP (client-side prototype pollution), turn it on in the DOM Invader settings.

DOM Invader settings

And try some DOMInvader prototype pollution test cases like prototype-pollution-query-string-gadget to check it works: See this Portswigger vid for the entire explanation.

DOM Invader settings

To confirm the vulnerability, click on Test and in the new tab that appears Inspect element -> DOM Invader to view Object:

DOM Invader settings

Type Object.prototype and enter:

DOM Invader settings

To find gadgets, click on Scan for Gadgets and in the new tab that appears Inspect element -> DOM Invader

DOM Invader settings

In this example, DOM Invader has discovered a gadget called “html”, which ends up in an innerHTML sink. A green “Exploit” button has appeared, combining the source discovered with the gadget and automatically creating a prototype pollution exploit.

Detecting SSPP with the Server-Side Prototype Pollution Scanner

Server-Side Prototype Pollution Scanner

  • Install the Server-Side Prototype Pollution Scanner extension from the BApp Store and make sure that it is enabled.

  • Explore the target website using Burp’s browser to map as much of the content as possible and accumulate traffic in the proxy history.

  • In Burp, go to the Proxy -> HTTP history tab.

  • Filter the list to show only in-scope items.

  • Select all items in the list.

  • Right-click your selection and go to Extensions -> Server-Side Prototype Pollution Scanner -> Server-Side Prototype Pollution, then select one of the scanning techniques from the list.

  • When prompted, modify the attack configuration if required, then click OK to launch the scan.

In Burp Suite Professional, the extension reports and prototype pollution sources it finds via the Issue activity panel on the Dashboard and Target tabs. If you’re using Burp Suite Community Edition, you need to go to the Extensions -> Installed tab, select the extension, then monitor its Output tab for any reported issues.

Bypassing input filters for server-side prototype pollution

Websites often attempt to prevent or patch prototype pollution vulnerabilities by filtering suspicious keys like __proto__. This key sanitisation approach is not a robust long-term solution as there are a number of ways it can potentially be bypassed:

  • Obfuscate the prohibited keywords, so they’re missed during the sanitization.

  • Access the prototype via the constructor property instead of __proto__.

Escalation

Impact varies, depending on the application logic and implementation, and includes DoS, and interfering with the JavaScript environment.

It is also a starting point for further attacks: A prototype pollution attack allows for leveraging gadgets loaded in the same context. These can potentially be used for escalating privileges or gaining access to sensitive information.

Portswigger labs

Remediation

  • Object.freeze will mitigate almost all cases. It blocks all changes to an object’s attributes. A prototype is an object which can be frozen like any regular object. Invoke the Object.freeze(Object.prototype) element to freeze the default prototype and prevent it from being polluted. The nopp npm package freezes all common object prototypes automatically.

  • Using schema validation to ensure that the JSON data contains the expected attributes. This will remove __proto__ if it appears in the JSON.

  • Use Map primitive (See ECMAScript® 2015 Language Specification).

  • Use the Object.create() method instead of the object constructor Object() or the object-literal {} when creating a new object. This allows for setting the created object’s prototype directly using the first argument passed to the Object.create() element. Objects created using the Object.create(null) function will not have the __proto__ attribute.

  • In general, pay attention when merging two objects recursively, recursively nesting properties, deep cloning of objects, and creating objects by recursively zipping properties with values. These are more prone to Prototype Pollution vulnerabilities than other functions. Whenever a library recursively sets a nested property, it must sanitise the untrusted inputs. Use safe open source libraries when recursively setting object’s properties.

Resources