Prototype Pollution

Introduction

When people hear javascript vulnerabilities most people think of cross site scripting(XSS). However, there are other types of vulnerabilities that impact javascript and one of them is prototype pollution. This type of vulnerability has risen in popularity over the past few years and in some cases this has lead to remote code execution(RCE). If you’r inspecting javascript files for vulnerabilities make sure to keep your eye our for this one.

Prototypes

Javascript is a prototype based language. Prototypes are the mechanism by which JavaScript objects inherit features from one another. This means that if the prototype object is modified in one object it will apply to every other object as shown in the below example:

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”.

Prototype Pollution

As stated earlier javascript is a prototype based language, this means that if we modify the prototype object it will persist to all other objects. Take a look at the following code, the goal here is to set the “admin” variable to true:

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.

Conclusion

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.