-
Notifications
You must be signed in to change notification settings - Fork 325
Description
combinedOverrides[symbol] = inputOverrides[symbol] |
Most JavaScript objects inherit the properties of the built-in Object.prototype
object. Prototype pollution is a type of vulnerability in which an attacker is able to modify Object.prototype
. Since most objects inherit from the compromised Object.prototype
object, the attacker can use this to tamper with the application logic, and often escalate to remote code execution or cross-site scripting.
One way to cause prototype pollution is by modifying an object obtained via a user-controlled property name. Most objects have a special __proto__
property that refers to Object.prototype
. An attacker can abuse this special property to trick the application into performing unintended modifications of Object.prototype
.
POC
In the vulnerable below, the untrusted value req.params.id
is used as the property name req.session.todos[id]
. If a malicious user passes in the ID value __proto__
, the variable items
will then refer to Object.prototype
. Finally, the modification of items
then allows the attacker to inject arbitrary properties onto Object.prototype
.
let express = require('express');
let app = express()
app.put('/todos/:id', (req, res) => {
let id = req.params.id;
let items = req.session.todos[id];
if (!items) {
items = req.session.todos[id] = {};
}
items[req.query.name] = req.query.text;
res.end(200);
});
One way to fix this is to use Map objects to associate key/value pairs instead of regular objects, as shown below:
let express = require('express');
let app = express()
app.put('/todos/:id', (req, res) => {
let id = req.params.id;
let items = req.session.todos.get(id);
if (!items) {
items = new Map();
req.sessions.todos.set(id, items);
}
items.set(req.query.name, req.query.text);
res.end(200);
});
Another way to fix it is to prevent the __proto__
property from being used as a key, as shown below:
let express = require('express');
let app = express()
app.put('/todos/:id', (req, res) => {
let id = req.params.id;
if (id === '__proto__' || id === 'constructor' || id === 'prototype') {
res.end(403);
return;
}
let items = req.session.todos[id];
if (!items) {
items = req.session.todos[id] = {};
}
items[req.query.name] = req.query.text;
res.end(200);
});
References
Object.prototype.proto
Map
CWE-78.
CWE-79.
CWE-94.
CWE-400.
CWE-471.
CWE-915.