JavaScript, often abbreviated JS, is a programming language that is one of the core technologies of the World Wide Web, alongside HTML and CSS. As of 2022, 98% of websites use JavaScript on the client side for webpage behavior, often incorporating third-party libraries. It is a very common and widely used programming language.

It is an Object Oriented Programming language, where we use the concept of prototyping of objects. This blog will focused on the vulnerability occurs in object prototyping, it’s causes and how the preventive measures related to protype pollution.

This blog will cover the following Segments:

  1. Basic introduction about the prototype in JavaScript
  2. What is prototype pollution?
  3. Impact of prototype pollution
  4. Identification of the vulnerability
  5. Affected libraries with this vulnerability
  6. Preventive measures.

A basic introduction to Prototype in JavaScript

What is a prototype?

A prototype is an attribute related to an object, it is used as a mechanism that enables JavaScript objects to inherit features from one another. Since almost everything in JavaScript is an object, a prototype is an object too.

Understandable definition:

JavaScript is prototype-based: when new objects are created, they carry over the properties and methods of the prototype “object”, which contains basic functionalities such as toString, constructor, and hasOwnProperty.

It defines from where you stated your object creation it gives you default things to you to object. Prototype defines the object structure and its properties.

An objects prototype may also have a prototype, and from it, it can inherit its prototype or other attributes, and so on. This is referred to as a prototype chain.

Let’s understand this with the help of an example.

Here I have created an object name customer in JavaScript.

Object Creation in JavaScript

Now run this JS and check it in a browser console. Here we can see our object along with the prototype.

This prototype contains all the properties in pre inherited by this object on creation

Prototype Containing all the pre inherited properties

What is Prototype Pollution?

Prototype pollution is an injection attack that targets JavaScript runtimes. With prototype pollution, an attacker might control the default values of an object’s properties. This allows the attacker to tamper with the logic of the application and can also lead to denial of service or, in extreme cases, remote code execution.

Prototype pollution occurs when an attacker manipulates __proto__ property of an object, usually by adding a new prototype onto __proto__. Since __proto__ exists for every object, and every object inherits the prototypes from its prototype, this addition is inherited by all the JavaScript objects through the prototype chain.

Flow Chart of Prototype Pollution Attack

Impact of Prototype Pollution

NOTE: The impact of prototype pollution depends on the application

The most common way to cause prototype pollution is to use an unsafe merge or extend function to recursively copy properties from an untrusted source object.

Figure 4 : Attacks Possible with Prototype Pollution

  • Depends on the application logic.
  • If it can bypass authorization, then the impact is high.
  • We can crash the application.
  • It can cause other dangerous vulnerabilities such as RCE (Remote Code Execution), IDOR (Insecure Direct Object References), Bypass Auth, and other vulnerabilities, namely XSS.

Root cause of the vulnerability

In JavaScript, during the declaration of class, the prototype is modified at runtime. This means that by default, the program can at any point in time add, change or delete entry in the prototype of a class.

In JavaScript there is no distinction between a property and an instance function. So instance function and other properties are accessed in the exact same way. There are two notations to access property in JavaScript.

  • The dot notation: Ex.-
1obj.a
  • The square bracket notation: Ex.-
1obj["a"]

Dot and Square Bracket Notation

Dot and Square Bracket Notation

Figure 5: Dot and Square Bracket Notation

There are many properties that exist by default on the object prototype, out of which “__proto__” is a property which returns prototype of the class of the object.

Let’s take an example:

Here I have created an object name “testobj” . Now using “__proto__” property I am changing the prototype at run time using square bracket notion method.

Figure 6: Code of Changing Prototype at Runtime

Figure 7: implementation of Changing Prototype at Runtime

The general idea behind prototype pollution starts with the fact the attacker has control over least the parameter “a” and “value” of any expression of the following form:

1Object[a][b] = value

If the attacker has control over the values, the attacker can set “a” to “__proto__” and the property with the name defined by “b” and it will be defined on all existing object (of the class of “obj”) of the application with the value “value”.

Note: If the object that you are polluting is not an instance of “object” remember that you can always move up the prototype chain by accessing the “__proto__” attribute of the prototype (ex.: “inst.__proto__.__proto__” points to the prototype of “Object”).

Identification of the vulnerability in the libraries.

To identify this vulnerability, try to find these operations in the source code.

  • Merge Operation

It is common in JavaScript that you want to merge two objects. This is how such a merge operation looks like the following code snippet.

code snippet

 1         varmerge = function (target, source) {
 2             for (varattrinsource) {
 3                 if(typeof(target[attr]) === "object" && typeof(source[attr]) === "object") {
 4
 5                     merge(target[attr], source[attr]);
 6                 } else {
 7                     target[attr] = source[attr];
 8                 }
 9             }
10             returntarget;
11         };

Working:

The merge operation iterates through the source object and will add whatever property is present in it to the target object.

Let us understand with an example.

 1        vartar = {a:1}
 2
 3        varsou = {a:3, d:2}
 4
 5        //Merge code snippet
 6
 7        varmerge = function (target, source) {
 8
 9            for (varattrinsource) {
10
11                if(typeof(target[attr]) === "object" && typeof(source[attr]) === "object") {
12
13                    merge(target[attr], source[attr]);
14
15                } else {
16
17                    target[attr] = source[attr];
18
19                }
20
21            }
22
23            returntarget;
24
25        };
26
27        varc = merge (tar, sou);
28
29        console.log(c)

In our example, tar is our target object and sou are our source object, now it will iterate all the properties of the sou object and then merge them with the tar object.

The output will look like

Figure 7: Example of merge operation

Attack:

Let us take a scenario where a user enters data in the application and the application is storing is an object. Now the application is merging this with other objects.

What can an attacker do?

An attacker can pass this payload to our merge operation, it will completely pollute our object prototypes.

To pollute the prototype, the attacker needs to provide the JSON data that has the _ __proto__ _ property.

1Payload: {b: 2, "\_\_proto\_\_": {"test": "pass"}}

After entering payload code will look like:

 1        vartar = {a:1};
 2
 3        varsou = JSON.parse('{"a": 15, "\_\_proto\_\_": {"test": "pass"}}');
 4
 5        //Merge code snippet
 6
 7        varmerge = function (target, source) {
 8
 9            for (varattrinsource) {
10
11                if(typeof(target[attr]) === "object" && typeof(source[attr]) === "object") {
12
13                    merge(target[attr], source[attr]);
14
15                } else {
16
17                    target[attr] = source[attr];
18
19                }
20
21            }
22
23            returntarget;
24
25        };
26
27        varc = merge (tar, sou);
28
29        console.log(c)

After entering the payload output will look like this:

Figure 8: Example of prototype pollution using merge operation

Note -> This makes things complicated if the source is supplied by a 3rd party.

  • Clone Operation:

Used for cloning an object and based on merge operation.

This is how such a clone operation looks like in the following code snippet.

1        functionclone(a)
2
3        {
4
5            returnmerge ({}, a);
6
7        }

As shown in the code, it is using the merge operation, as seen in the previous section.

The main difference here is that the target object is an empty object.

Attack:

 1        varmerge = function (target, source) {
 2
 3            for (varattrinsource) {
 4
 5                if(typeof(target[attr]) === "object" && typeof(source[attr]) === "object") {
 6
 7                    merge(target[attr], source[attr]);
 8
 9                } else {
10
11                    target[attr] = source[attr];
12
13                }
14
15            }
16
17            returntarget;
18
19        };
20
21        functionclone(a)
22
23        {
24
25            returnmerge ({}, a);
26
27        }
28
29        vara = JSON.parse('{"a":1,"\_\_proto\_\_": {"test": "pass"}}');
30
31        varb= clone(a);
32
33        console.log(b);

Same attack scenario as shown in merge operation. Here our source object is a.

1        Payload: {"a" : 1 , "\_\_proto\_\_": {"test" : "pass"}}

After entering payload output will looks like:

Figure 9: Example of prototype pollution using clone operation

  • Path Assignment Operation

Figure 10: code snippet of Path assignment operation

As you have seen in the above image, this is the operation in which we can set the value of any object’s property.

Also, the function setvalue() is user-defined, it can be any function that is performing the same operation.

For demo purposes, I have created a function, which looks like the following code snippet.

1        functionsetvalue(objname, objprop, propvalue)
2
3        {
4
5            objname[objprop] = propvalue;
6
7        }

Here, it is taking three inputs including “object name”, “property name of object”, and “value” and assigning the value to the provided property value.

Let’s understand by an example.

 1        functionsetvalue(objname, objprop, propvalue)
 2
 3        {
 4
 5            objname[objprop] = propvalue;
 6
 7        }
 8
 9        vartest = JSON.parse('{"a": 1, "b" : 2}')
10
11        setvalue(test, "a", 3);
12
13        console.log(test)

Here, we have an object name test, which has two properties a and b with values 1 and 2 respectively.

Here we are calling the function set value, which will change the value of the property from 1 to 3.

Figure 11: code snippet of Path assignment operation

Attack:

Let’s consider an application using this kind of functionality, in which it is taking input from the user and directly passing it to the function.

Here an attacker can input “__proto__ “, in the field of object property name and can pollute the prototype.

How does the attack code look like

 1        functionsetvalue(objname, objprop, propvalue)
 2
 3        {
 4
 5            objname[objprop] = propvalue;
 6
 7        }
 8
 9        vartest = JSON.parse('{"a": 1, "b" : 2}')
10
11        setvalue(test, "\_\_proto\_\_", {"test" :"pass"});
12
13        console.log(test)

Figure 12: Example of prototype pollution using Path assignment operation

Affected libraries with this vulnerability

  • Lodash

Figure 13: Example of lodash library

– Just-Extend

Figure 14: Example of just-Extend library

Mitigations

  • Input validation
  • Use a JavaScript library that is using safe merge, clone, extend, or path assignment operations to recursively copy properties from an untrusted source object.
  • Consider Using Object. null() which has no prototype.

Figure 15: Prevention using Object.null

  • You can use a map instead of an object.
  • Freez the prototype. 16RackMultipart20220830-1-jokkjp_html_2b3e210472199fe7.png)

Conclusion

You’ve learned what prototype pollution is and how to protect your applications from it. We hope you will apply your new knowledge wisely and make your code safer.

Practice labs

https://github.com/abhiabhi2306/prototype-pollution/

https://github.com/rafax00/PrototypePollution-Lab

https://github.com/Dheerajmadhukar/Prototype-Pollution-Lab_me_dheeraj

https://msrkp.github.io (Only XSS)

References:

About Payatu

Payatu is a research-powered, CERT-in empanelled cybersecurity consulting company specializing in security assessments of IoT (Internet of Things) product ecosystem, Web application & Network with a proven track record of securing applications and infrastructure for customers across 20+ countries.

Want to check the security posture of your organization? Browse through Payatu’s Service and get started with the most effective cybersecurity assessments.

Have any specific requirements in mind? Let us know about them here and someone from our team will get in touch with you.

Subscribe to our Newsletter
Subscription Form
DOWNLOAD THE EBOOK

Fill in your details and get your copy of the ebook in few seconds

Ebook Download
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download ICS Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Cloud Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download IoT Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Code Review Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Red Team Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download AI/ML Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download DevSecOps Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download Product Security Assessment Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download AI/ML Sample Report
DOWNLOAD A SAMPLE REPORT

Fill in your details and get your copy of sample report in few seconds

Download IoT Sample Report

Let’s make cyberspace secure together!

Requirements

Connect Now Form

What our clients are saying!

Trusted by