Consider the following example of a constructor named Shape:
A new object instance of the Shape object is created using the keyword new.
The inheritance schema can be illustrated as such:
The following shows the prototype chain where the __proto__ property of the objects are accessed. It can be seen that accessing beyond Object.prototype returns null. (Note that prototype is a property of a class constructor whereas __proto__ is the property of that class instance; they are not the same)
Since the square instance contains properties from Object.prototype, it is possible to call functions such as square.toString() or square.getPropertyOf().
Object manipulation is possible by assigning values to __proto__ since this property of Object.prototype is a getter and setter function (More information here). Prototype pollution occurs when an attacker is able to assign values to and modify __proto__and change the behavior of the application. Since objects inherit the prototypes from the prototype chain, polluting Object.prototype causes every subsequent new instance of a JavaSscript object to be polluted.
The following shows the modification of the toString() function in Object.prototype through prototype pollution, resulting in the inheritance of the polluted toString() function when a new instance of an object is created:
The inheritance schema illustrates the testObject inheriting the properties from Object.prototype after the pollution:
An example of a vulnerable program is:
If an attacker controls userInput1 and userInput2, they can set __proto__ to an arbitrary value via userInput2, resulting in the modification of Object.prototype.
Although this is a contrived example, there have been unsuspecting real-world applications that provide such conditions under certain circumstances.
Is it Prototype Pollution?
Let us consider the following program which attempts to pollute Object.prototype through the usage of JSON.parse().
The same behavior can be seen in Ramda. This proof-of-concept was thought to demonstrate the prototype pollution through Ramda’s mapObjIndexed() initially.
However, upon creating a new instance of an object, it was found that the new object did not inherit the supposedly polluted __proto__ property. This meant that Object.prototype was not modified or polluted.
If prototype pollution can be defined as unauthorized and unintended modifications to Object.prototype that cause every new object to inherit the modified properties, then it can be assumed that JSON.parse(), Ramda’smapObjIndexed() or Object.assign()are not vulnerable to prototype pollution.