on
My take on Prototype pollution
With the recent release of a new prototype pollution scanner on Github, I’ve been seeing more and more issues related XSS caused by prototype pollution and guessed its time I write an article about it.
Basic knowledge about JavaScript
Before I dive into the technical causes of prototype pollution, let me introduce to 3 main terms that will be used quite frequently in this article - Objects
, Prototype
and finally, __proto__
.
Object
can be understood as a key-value pair in JavaScript, where the key is a string and the value can be anything (literally anything). For those familiar to Python, Object
is in a sense similiar to our map or dictionary. Everything that we type in JavaScript is an Object
.
Prototype
can be understood as an attribute that is related to an Object
and is a mechanism used by JavaScript to inherit attributes or features from one Object
to another. However, since we know that everything we use in JavaScript is also an Object
, Prototype
is also an Object
.
__proto__
is a prototype chain which refers to all the prototypes
of an object and every single Object
in JavaScript has __prototype__
as their attribute. When __prototype__
was implmented, it was meant to be created as a feature to support class inheritance etc. However, such a feature introduced a vulnerability in it, which is prototype pollution that we are going to talk about today.
What is prototype pollution
Prototype pollution occurs when a malicious actor manipulates the __proto__
either by adding new prototypes into __proto__
or by modifying existing prototypes in __proto__
. Since every Object
has __proto__
as their attribute, the addition of new prototypes/modification of existing prototypes are inherited by all the objects.
The consequence of this would be that this opens up a new attack surface where malicious actors can actually inject malicious code to carry out Remote Code Execution Attacks or to cause Reflected XSS attacks by triggerring exceptions.
Mitigations to prototype pollution
The first mitigation would be to use Object.freeze
. Freezing any Object
will prevent new Prototypes
from being added to the Object
. However, such a mitigation contains a risk of breaking any system, especially larger commerical sites where it may affect the inheritance of features or functionality between Objects
Another alternative would be to sanitize the inputs on our payloads such as our URLs, JSON input etc. to remove suspicious characters such as __prototype__
.
One other alternative is to replace Object
primitives with Map
. However, this change might not be feasible to be implemented especially in commercial sites with large code base since this would mean a large change would have to be made to the code base which might pose the possibility of breaking the system.
Conclusion
In the upcoming years, there is not plans to remove __proto__
yet and so, prototype pollution is likely to continue to be widely exploited. In my own opinion, the best prevention against prototype pollution would still be a proper sanitization of client-side inputs to remove suspicious characters or payloads.