Prototype pollution
Prototype pollution is a vulnerability where an attacker is able to inject properties into the top level JavaScript prototype. This basically adds an attacker defined property to all JavaScript objects. While this might seem unimportant, the impacts of this are quite severe.
What is prototype pollution?
In JavaScripts, inheritance is implemented via prototypes. Each object has a __proto__
property that is another object. The object inherits all properties in its __proto__
. In JS, almost all objects are subclasses of Object
, thus share its prototype. This means that if we set a value on a.__proto__
it will most likely affect other objects as well. Here's an example:
a = {name: "jro"}
b = {name: "sus"}
b.__proto__.sus = "yes"
console.log(a.sus)
// => yes
However, prototype pollution is unable to overwrite existing properties:
a = {name: "jro", sus:"no"}
b = {name: "sus"}
b.__proto__.sus = "yes"
console.log(a.sus)
// => no
Impacts of prototype pollution
While prototype pollution might be viewed as a low severity vulnerability, the right conditions can enable prototype pollution to have severe impacts.
Authentication bypass
Consider this code:
a = {name: "jro"}
b = {name: "sus"}
b.__proto__.admin = true
console.log(a.admin)
// true
Prototype pollution can also occur on the client side
RCE
When prototype pollution occurs in server side code and a templating engine is used, an attacker is often able to set internal properties in the templating engine, resulting in RCE.
See gunship.
Identifying prototype pollution
Libraries such as certain versions of lodash and the flat
library perform unsafe object unpacking that enable prototype pollution. Suspiciously written code that assigns arbitrary values to arbitrary properties could be indicative of prototype pollution.