A new class of security flaw is emerging from obscurity

Prototype pollution vulnerability impacts JavaScript applications

In early 2019, security researchers at Snyk disclosed details of a severe vulnerability in Lodash, a popular JavaScript library, which allowed hackers to attack multiple web applications.

The security hole was a prototype pollution bug – a type of vulnerability that allows attackers to exploit the rules of the JavaScript programming language and compromise applications in various ways.

What is prototype pollution?

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.

Object-based inheritance gives JavaScript the flexibility and efficiency that web programmers have come to love – but it also makes it vulnerable to tampering.

Malicious actors can make application-wide changes to all objects by modifying object, hence the name prototype pollution.

Interestingly, attackers don’t even need to directly modify object – they can access it through the ‘__proto__’ property of any JavaScript object. And once you make a change to object, it applies to all JavaScript objects in a running application, including those created after tampering.

Read more of the latest JavaScript security news

Here’s a simple example of how prototype pollution works. The following code changes the value of the toString function in the prototype to an arbitrary code:

let customer = {name: "person", address: "here"}
//output: "[object Object]"

customer.__proto__.toString = ()=>{alert("polluted")}
// alert box pops up: "polluted"

Now, every time toString() is called on an object, an alert box will pop up with the message “polluted” (unless an object explicitly overrides Object.toString() with its own implementation). Since toString is widely used in client-side JavaScript, this will cause disruption in the application’s execution.

Other prototype pollution attacks involve adding properties and methods to object to manipulate the behavior of an application.

“[Prototype pollution] is not completely unique, as it is, more or less, a type of object injection attack,” security researcher Mohammed Aldoub tells The Daily Swig. “However, it is special in that it is definitely not one of the mainstream vulnerability types most people know about.

“It is obscure because it mainly targets specific languages/frameworks, and because it is not as well documented as others. It is, however, not any less dangerous than other ‘mainstream’ vulns.”

What is the impact of prototype pollution?

“The impact of prototype pollution depends on the application,” security researcher Michał Bentkowski tells The Daily Swig.

“In a nutshell, every time a JavaScript code accesses a property that doesn’t exist on an object (which includes checking the existence of the property), we can change the outcome of the check with prototype pollution.”

He added: “Depending on the exact logic of the application, prototype pollution can lead to practically all popular web vulnerabilities: remote code execution (RCE), cross-site scripting (XSS), SQL injection, and so on.”

On web browsers, prototype pollution commonly leads to XSS attacks (see example above). In 2019, for instance, a prototype pollution bug found in JavaScript library jQuery left many web applications vulnerable to such assaults.

YOU MAY ALSO LIKE Denial-of-Wallet attacks: How to protect against costly exploits targeting serverless setups

But other vulnerabilities are likely to surface. “Client-side exploitation of prototype pollution is not currently well covered,” says Bentkowski, who is currently working on a detailed account of how exploits in this category can bypass popular HTML sanitizers such as html-sanitize and DOMPurify.

On the server side, the impact of prototype pollution is better known.

“The impact of the prototype pollution on server-side is at least denial of service by causing the Node.js server to crash,” security researcher Posix tells The Daily Swig. “However, it certainly has the potential to link to other vulnerabilities, such as remote code execution.”

The Node.js ecosystem has been hit by prototype pollution exploits over recent monthsThe Node.js ecosystem has been hit by prototype pollution exploits over recent months

Last year, Bentkowski discovered a prototype pollution bug in Kibana, a data visualization library, which made it possible to create a reverse shell and achieve RCE.

Then in July this year, Posix reported the same type of flaw in the popular express-fileupload library, which could allow a hacker to obtain remote-shell access to a Node.js server.

In the same month, security researcher Francesco Soncina discovered a prototype pollution vulnerability in the object-mapping JavaScript library TypeORM that allowed hackers to stage SQL injection attacks on Node.js applications.

“If the end application depending on the library has dynamic code evaluation or command execution gadgets, the attacker can potentially trigger arbitrary command execution on the target machine,” Soncina wrote.

And in September 2020, Snyk reported that a carryover function in the popular node-forge JavaScript library contained a vulnerability that could allow attackers to carry out prototype pollution attacks against applications.

The vulnerability was given a high-severity 9.8 score and a proof of concept showed that setPath can be used to pollute the __prototype__ property of the base Object, resulting in application-wide modifications.

How to harden applications against prototype pollution attacks

Like many other security vulnerabilities, attackers exploit prototype pollution bugs through user input in web applications, and sending their malicious code in text fields, headers, and files.

“I guess trusting user input is the actual root of the problem, so developers should be very careful about which object fields can be influenced by users,” Aldoub says.

Another problem is the way many JavaScript applications are written. “The coding pattern that leads to prototype pollution is extremely common in JavaScript code,” Bentkowski points out.

For instance, many JavaScript libraries accept an options object and check the object for the presence of specific properties. In case some property is not present, they default to some predefined option (example below).

options.someOption = options.someOption || default.someOption;

In this case, attackers can use prototype pollution to override someOption and manipulate the logic of the application.

One popular kind of defense it to create blocklists where developers remove risky fields from input strings. But this is easier said than done.

RECOMMENDED TrojanNet – a simple yet effective attack on machine learning models

“You have to enumerate all possibilities of risky fields, and all permutations to encode such fields, which is an immeasurably difficult feat,” Aldoub says.

For instance, with the aforementioned Lodash vulnerability, developers initially checked strings against the field __proto__, but then realized that constructor was also a potential target for prototype pollution.

“What if another field was then discovered to be exploitable?” Aldoub says.

Another important step is checking dependency modules of potential prototype pollution vulnerabilities, which presents its own challenges.

“From an application developer’s point of view, it is very difficult to check all the modules in use,” Posix explained. “Therefore, before use, it is necessary to verify that the module is fully validated.”

An underrated bug

All the researchers The Daily Swig spoke to voiced a common concern: that prototype pollution is not getting enough attention.

“I felt infinite potential in this type of vulnerability. But compared to the possibilities, I don’t think enough research has been done,” says Posix, who has been focusing on prototype pollution attacks since last year.

“The community needs to learn and practice this type of vulnerability in more depth and with more attention, since it is still obscure and dangerous,” Aldoub says.

Bentkowski adds: “Prototype pollution can have a serious impact on the security of web applications but there aren't many sources out there that show real-world cases of its exploitation.

“So, this is a perfect target for research,” says the researcher, drawing an analogy with Java deserialization, another dangerous type of vulnerability that was mostly unnoticed for many years.

A presentation by security researchers at FoxGlove in 2015 showed the destructive potential of Java deserialization and finally gave it the traction it deserves in the security community.

“I feel that this kind of breakthrough is still to come for prototype pollution,” Bentkowski says.

READ MORE What is Fetch Metadata? How to protect your web resources from information-stealing attacks