CWE-1321: Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')
Learn about CWE-1321 (Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')), its security impact, exploitation methods, and prevention guidelines.
What is Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')?
• Overview: Improperly Controlled Modification of Object Prototype Attributes, known as 'Prototype Pollution', is a vulnerability where an attacker can manipulate the properties of an object prototype. This allows the attacker to create or alter attributes that apply to all objects, potentially introducing malicious behavior or disrupting application logic.
• Exploitation Methods:
- Attackers can exploit this vulnerability by injecting malicious input that changes the prototype attributes of objects, often through special properties like
__proto__
,constructor
, orprototype
. - Common attack patterns include sending crafted JSON payloads that modify object prototypes during object property assignment or merging operations.
• Security Impact:
- Direct consequences of successful exploitation include unauthorized attribute creation or modification in objects, leading to unexpected application behavior or security bypass.
- Potential cascading effects include breaking application logic, causing denial of service, or enabling further attacks such as code execution.
- Business impact may involve data breaches, service disruption, loss of customer trust, and potential legal liabilities.
• Prevention Guidelines:
- Specific code-level fixes include validating and sanitizing input to ensure it cannot modify the prototype chain, and using safe methods to copy or merge objects that do not involve prototype properties.
- Security best practices involve avoiding direct manipulation of object prototypes and using Object.create(null) for objects that do not inherit from the default prototype.
- Recommended tools and frameworks include using libraries like lodash with prototype-pollution mitigations, and employing static analysis tools to detect potential prototype pollution vulnerabilities during development.
Technical Details
Likelihood of Exploit: Not specified
Affected Languages: JavaScript
Affected Technologies: Not specified
Vulnerable Code Example
// A function that merges properties from the source object into the target object
function merge(target, source) {
for (let key in source) {
// Vulnerable line: Directly assigns properties from source to target
target[key] = source[key];
}
}
let userPreferences = {};
let maliciousPayload = JSON.parse('{"__proto__": {"admin": true}}');
// Merging malicious payload into user preferences
merge(userPreferences, maliciousPayload);
// Prototype pollution occurs: userPreferences.admin is now true
console.log(userPreferences.admin); // true
console.log(({}).admin); // true, because Object.prototype has been polluted
How to fix Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')?
To fix prototype pollution vulnerabilities, you need to ensure that malicious input cannot modify the prototype of objects. This typically involves checking for and preventing the use of special properties such as __proto__
, constructor
, and prototype
.
Steps to fix:
- Validate Keys: Ensure that the keys being merged do not include dangerous keys that can lead to prototype pollution.
- Use Object.create(null): Use objects without prototypes as targets if possible.
- Use Object.hasOwn(): Ensure that properties are only set if they are not on the prototype chain.
Implementing these principles can prevent prototype pollution by disallowing any unintended modification of the prototype chain.
Fixed Code Example
// A secure function to merge properties while preventing prototype pollution
function secureMerge(target, source) {
for (let key in source) {
if (Object.hasOwn(source, key)) { // Check if the property is directly on the source object
// Prevent prototype pollution by checking key names
if (key !== "__proto__" && key !== "constructor" && key !== "prototype") {
target[key] = source[key];
}
}
}
}
let userPreferences = {};
let safePayload = JSON.parse('{"theme": "dark"}');
// Merging safe payload into user preferences
secureMerge(userPreferences, safePayload);
// No prototype pollution occurs: userPreferences.admin remains undefined
console.log(userPreferences.theme); // "dark"
console.log(userPreferences.admin); // undefined
console.log(({}).admin); // undefined, Object.prototype is safe
In the fixed code, we utilize Object.hasOwn()
to ensure that only properties directly on the source object are considered. We also include checks to prevent any properties that could lead to prototype pollution, such as __proto__
, constructor
, and prototype
, from being copied over. This ensures that the prototype chain of objects remains intact and unaltered by external inputs.