Web Security & OWASP (50 Qs)•Part 4: Browser Security, HTTP Headers & Client Hardening (36 - 42)
Prototype Pollution in JavaScript: Recursive object merge flaws and defensive hardening techniques.
What is Prototype Pollution?
In JavaScript, objects inherit properties from Object.prototype. Prototype Pollution occurs when an attacker injects properties into a dynamic object using special keys like __proto__ or constructor.prototype, causing properties to be added to all objects across the entire Node.js or browser runtime.
javascript
// Vulnerable recursive merge function
function deepMerge(target, source) {
for (let key in source) {
if (typeof source[key] === 'object') {
if (!target[key]) target[key] = {};
deepMerge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
return target;
}
// Attacker Payload (e.g. from JSON body parse)
const maliciousPayload = JSON.parse('{"__proto__": {"isAdmin": true}}');
deepMerge({}, maliciousPayload);
// Catastrophic Result: ALL newly created objects now inherit isAdmin: true!
const regularUser = {};
console.log(regularUser.isAdmin); // true! Privilege Escalation or RCE!
Defensive Hardening Techniques
- Freeze the Object Prototype:
javascript
Object.freeze(Object.prototype); // Throws error if any code attempts to pollute it!
- Create Objects without Prototypes:
javascript
const cleanMap = Object.create(null); // No prototype! Has no __proto__ property.
- Use Map instead of raw Objects:
javascript
const safeMap = new Map(); // Built-in protection against prototype key lookups.
- Block Dangerous Keys during Merges:
javascript
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
continue; // Ignore and discard
}