Page cover

Prototype Pollution

Javascript

JavaScript is the most popular programming language for the web. It makes websites interactive by adding features like form checks, animations, pop-ups, and dynamic content. Over time, JavaScript has grown beyond just the browser. With tools like Node.js, it can also be used on servers, allowing developers to build full websites and applications using the same language.

Object:

Objects in JavaScript are dynamic, prototype-based reference types that can hold both data and behavior.

var my_object={
			"name":"0x51B1",
			"age":24,
			"isAdmin":true
}

//{name: '0x51B1', age: 24, isAdmin: true}

in JavaScript, practically everything is an object, and inherits from parent object.

JavaScript is not a conventional object-oriented language. It’s a prototype-based object-oriented language, which is how this inheritance works.

JavaScript doesn’t have objects that other languages like Java might use, with features like inheritance and classes – instead, these JavaScript objects rely on a special property called proto (or prototype), which points to that object’s ‘prototype’, allowing it to inherit properties and methods.

All the ‘class’ and ‘extends’ type syntax that you might see in modern JavaScript is just a kind of wrapper around prototype-based inheritance.

Prototype chain:

The prototype chain in JavaScript is the mechanism that allows objects to inherit properties and methods from other objects.

Here’s how it works:

  • Every JavaScript object has an internal link (called [[Prototype]], often accessed with __proto__) to another object, known as its prototype.

  • If you try to access a property or method on an object and it doesn’t exist there, JavaScript automatically looks for it in the object’s prototype.

  • This lookup continues up the chain until it reaches the top-level Object.prototype. If it’s not found there, JavaScript returns undefined.

> let obj={"name":"sibi","age":24}

> obj

// {name: 'sibi', age: 24}

> obj.__proto__.isAdmin=True

> obj

// {name: 'sibi', age: 24}

> obj.isAdmin

//True

isAdmin is added to the base object using the __proto__

Polluting the prototype

Prototype pollution is an injection attack aimed at JavaScript runtimes, where an attacker manipulates an object's prototype to alter its default property values. This can disrupt the application's logic, potentially leading to denial of service or, in extreme cases, remote code execution.

> var SomeObject = {}

> var obj = {}

> console.assert(user.isAdmin === true)
//Assertion failed

> SomeObject.__proto__.isAdmin === true
//true

> console.assert(user.isAdmin == true)
//undefied

> user.isAdmin
//true

Demo:

  • Since innerHTML is used to embed HTML into the page, it can be escalated into an XSS vulnerability.

  • Ensure that the code block executes only if the user has isAdmin privileges.

In mergeObjects, the default settings and custom settings are combined using mergeObjects(defaultSettings, customSettings);

Exploiting prototype pollution via the __proto__ property to set isAdmin to true.

Gained access to the variables: ID, Name, and Address info.

Injecting HTML through the id parameter.

Since the sink is in innerHTML, we can use an <img> tag to execute JavaScript.

Mitigation:

  • Block __proto__, constructor, prototype in user input.

  • Use Object.create(null) for safe objects.

  • Keep libraries updated and avoid unsafe merge functions.

Last updated