Every object has a __proto__ (or prototype) property too which points to that object’s ‘prototype’, allowing it to inherit properties and methods.
If we try to access a property that doesn’t exist on my_object, JavaScript will next look to see if it is part of the next Object’s proto property
empty_object = {}
Object.prototype.x = 'test'
console.log(empty_object.x) // test
// Empty object.
blank_object = {}
// Object with a few properties
my_object = {a:1, b:2}
// Define the 'z' property on the '__proto__' object of 'my_object':
my_object["__proto__"]["z"] = "test"
console.log(my_object.z) // Output: test
console.log(blank_object.z) // Output: test
console.log(Object.z) // Output: test
// Note: here we add a 'z' property on the __proto__ object of 'my_object',
// that in this case is "Object".
s = "test"
s.__proto__ // String { .... }
// Define the 'z' property on the '__proto__' object of 's':
s["__proto__"]["z"] = "bar"
console.log(s.z) // Output: bar
// Create another string ...
x = "test"
console.log(x.z) // Output: bar
// Create an object ...
obj = {}
console.log(obj.z) // Output: undefined
// Here we add a 'z' property on the __proto__ object of 's',
// that in this case is "String". So now all object all objects
// that inherit "String" object have this property.
The three most common JavaScript patterns that can lead to prototype pollution are merging, cloning, and value setting operations. Anytime an object is dynamically built from user input, there's a risk of prototype pollution.
Real World Example – jQuery Deparam
to do
Client-side prototype pollution (manual)
Finding sources
In the URL
Using a common XSS source, such as the URL parameters or hash, set a __proto__ payload, like this:
https://example.com/?__proto__[polluted]=Polluted
// or
https://example.com/#__proto__[polluted]=Polluted
// or
https://example.com/?__proto__.polluted=Polluted
Check Object.prototype in your browser console to see if the property was successfully added:
An important point is that the [] and . notations are not valid JavaScript in this context; they are defined by the developer. So the pattern you should look for in any source is ‘nesting’
Basically, here are defined method and body properties, but there are a number of other possible properties that we've left undefined. So, if you find a source, you can pollute Object.prototype with your own headers property.
An easy trap for developers is overlooking that a JavaScript for...in loop iterates over all of an object's enumerable properties, including inherited ones from the prototype chain.
// Example with "object"
const myObject = { a: 1, b: 2 };
// pollute the prototype with an arbitrary property
Object.prototype.foo = 'bar';
// confirm myObject doesn't have its own foo property
myObject.hasOwnProperty('foo'); // false
// list names of properties of myObject
for(const propertyKey in myObject){
console.log(propertyKey);
}
// Output: a, b, foo
// Example with "array"
const myArray = ['a','b'];
Object.prototype.foo = 'bar';
for(const arrayKey in myArray){
console.log(arrayKey);
}
// Output: 0, 1, foo
Warning: It's easy to unintentionally cause a denial-of-service (DoS), making testing in production risky. In addition, once a server-side prototype is polluted, the change persists for the entire lifetime of the Node process, with no way to reset it.
Detection - (polluted property reflection)
Attempt to pollute the global Object.prototype with an arbitrary property in a POST / PUT request