Prototype Pollution attack on NodeJS applications

The Prototype Pollution attack is a form of attack to the Object prototype in Javascript, leading to logical errors, sometimes leading to the execution of fragments Arbitrary code on the system.

Source: https://thehackernews.com

The Prototype Pollution attack ( as the name suggests partially) is a form of attack (adding / modifying / deleting properties) to the Object prototype in Javascript, leading to logical errors, sometimes leading to the execution of fragments Arbitrary code on the system (Remote Code Execution — RCE). This vulnerability has been discovered since 2018 in some popular JavaScript libraries, JQuery, and recently discovered this vulnerability in the Lodash library, one of the popular libraries. Let’s find out how this form of attack.

Objects in Javascript

First of all, we need to understand Object in javascript. An object is simply a collection of key and value pairs, often called properties of that object. For example:

Using {} helps us to declare a new object and assign it the corresponding name and age properties. After the declaration is complete, we can access these properties as usual. However, the inside of the user object has not only the properties that we have assigned but also a lot of other information as above. So where do these attributes come from?

In Javascript, Object is a basic object, the template for all newly created objects. It is possible to create an empty object by passing null to Object.create . However, the newly created object will also have a type that corresponds to the passed parameter and inherits all the basic properties.

console.log(Object.create(null)); // prints an empty object

Functions / Classes in Javascript

In Javascript, the concepts of the class and the function are quite interrelated (the function itself acts as the constructor for the class and the actual nature has no concept of “class” in javascript). Let’s see the following example:

In the example above, we have defined a function named person and initialized two objects named person1 and person2 . If we look at the properties of newly created objects, we may notice two things:

When the function is created, the javascript engine includes the prototype property in the function. prototype is an object that has a constructor property pointing to the function that contains it?

property in the function. is an object that has a constructor property pointing to the function that contains it? When the object is created, the javascript engine adds a __proto__ property to the newly created object, which refers to the prototype object of the constructor function. In short, the object.__proto__ points to function.prototype .

Constructor

Constructor is a special attribute that returns the function used to create that object. The object prototype has a constructor pointing to that function and the constructor of constructor will be the global constructor. For example:

Prototypes in JavaScript

One thing to note is that the prototype attribute can be changed/modified/deleted when executing the code. For example:

Above, we changed the prototype of the function and added a new property details . We can do the same thing by using objects:

Do you see anything strange? We change person1 but it affects person2 as well. The reason for this is that in the previous example, we changed person.prototype to add a new attribute but in the second example, we changed on an object. Because the constructor will return the function used to create an object, person1.constructor will refer to the function person and person1.constructor.prototype now is person.prototype .

Prototype Pollution

For example, obj[a][b] = value . If the attacker can control the value of a and value , then he only needs to adjust the value of a to __proto__ (in javascript, obj["__proto__"] and obj.__proto__ are completely equivalent) then property b of all existing objects in the application will be assigned to value .

However, the attack is not as simple as the one above, according to paper, we can only attack when one of the following three conditions is met:

Perform recursive merge

Property definition by path

Clone object

Let’s look through some errors:

CVE-2019–11358: Prototype pollution attack through jQuery $ .extend

$ .extend, if handled incorrectly, can change the properties of the object prototype (the template of the objects in the app). This attribute will then appear on all objects. Note that only the “deep” version (ie g) of $ .extened is affected.

Programmers often use this function to duplicate an object or fill in new properties from a default object. For example:

We can imagine myObject is an input field from the user and is serialized into the DB)

In this code, we often think, when running will assign the attribute isAdmin into the newly created object. But essentially, it is assigned directly to {} and then {}.isAdmin will be true . If after this code, we perform the following check:

If (user.isAdmin === true) {

// do something for admin

}

If the user has not yet existed ( undefined ), the property isAdmin will be searched in its parent object, which is the Object added isAdmin with the value true above.

Another example when executed on JQuery 3.3.1:

$.extend(true, {}, JSON.parse('{"__proto__": {"devMode": true}}'))

console.log({}.devMode); // true

These errors can affect a lot of Javascript projects, especially NodeJS projects, the most practical example is the error in Mongoose, the JS library that helps manipulate MongoDB, in December 2018.

CVE-2018–3721, CVE-2019–10744: Prototype pollution attack through lodash

Lodash is also a well-known library that provides a lot of different functions, helping us to write code more conveniently and more neatly with over 19 million weekly downloads. And It got the same problem as JQuery.

CVE-2018–3721

CVE-2019–10744

This bug affects all versions of Lodash, already fixed in version 4.17.11.

What can I do to prevent?