As you can see above we have two variables called “a” and “b”. We modify the prototype object in variable “a” by adding a variable called “foo” and giving it the value of “bar”. You might think that this would have no effect on variable “b” but it does. The modified prototype object is inherited by variable “b”, so when we call the “foo” variable on “b” it prints “bar”.
As shown above we are merging user supplied data with the user object. Next it will create a variable called admin and it will check if “admin.admin” is set to true. If it is, we win. Under normal circumstances this would be impossible as we never get the change to modify this variable but with prototype pollution we can.
During the merge process if it comes across a prototype object it will add that to the user object using the dangerous “merge” function. Since the prototype object is inherited by all other objects we can potentially modify other variables as shown in the below curl request.
In the above image we are sending a prototype object with a variable called “admin” which is set to “true”. When the line checks to see if admin.admin is set to true it will pass because the admin object inherited the admin variable from the prototype object which we modified.
Prototype pollution can be thought of as a type of object injection. The prototype object is inherited by all objects so if we can modify it in one place it will be inherited by everything else. This can be used to overwrite functions, variables, and anything else. Although this is a lesser known vulnerability it is just as deadly as anything else. In the past this has led to XSS, DOS attacks, and RCE so there is no limit to what you can potentially do with this.