112 lines
2.8 KiB
Plaintext
112 lines
2.8 KiB
Plaintext
== Why is this an issue?
|
|
|
|
Prototype Pollution vulnerabilities allow to inject new properties into the built-in ``++Object.prototype++`` object. Since most objects inherit from this prototype, it can result in unexpected behavior, e.g., crashes or more severe vulnerabilities.
|
|
|
|
|
|
In the past, it has led to the following vulnerabilities:
|
|
|
|
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-10744[CVE-2019-10744]
|
|
* http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-11358[CVE-2019-11358]
|
|
|
|
|
|
=== Noncompliant code example
|
|
|
|
For merge functions:
|
|
|
|
[source,javascript]
|
|
----
|
|
function for_in_merge(dst, src) {
|
|
for (let key in src) {
|
|
if (dst[key]) {
|
|
for_in_merge(dst[key], src[key]);
|
|
} else {
|
|
dst[key] = src[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
let obj1 = {};
|
|
for_in_merge(obj1, req.query.obj2); // Noncompliant
|
|
----
|
|
|
|
For set-path functions:
|
|
|
|
[source,javascript]
|
|
----
|
|
function for_set(target, path, value) {
|
|
let keys = path.split('.');
|
|
for (let i = 0; i < keys.length; ++i) {
|
|
let key = keys[i];
|
|
if (i < keys.length - 1) {
|
|
if (!target[key]) {
|
|
target[key] = {};
|
|
}
|
|
target = target[key];
|
|
} else {
|
|
target[key] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
for_set(req.query.path, req.query.val); // Noncompliant
|
|
----
|
|
|
|
|
|
=== Compliant solution
|
|
|
|
For merge functions:
|
|
|
|
[source,javascript]
|
|
----
|
|
function for_in_merge(dst, src) {
|
|
for (let key in src) {
|
|
// Recommended Secure Coding Practices: prevent sensible keys
|
|
if (key === "constructor" || key === "prototype" || key === "__proto__") {
|
|
continue;
|
|
}
|
|
|
|
if (dst[key]) {
|
|
for_in_merge(dst[key], src[key]);
|
|
} else {
|
|
dst[key] = src[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
let obj1 = {};
|
|
for_in_merge(obj1, req.query.obj2); // Compliant
|
|
----
|
|
|
|
For set-path functions:
|
|
|
|
[source,javascript]
|
|
----
|
|
function for_set(target, path, value) {
|
|
let keys = path.split('.');
|
|
for (let i = 0; i < keys.length; ++i) {
|
|
let key = keys[i];
|
|
// Recommended Secure Coding Practices: prevent sensible keys
|
|
if (key === "constructor" || key === "prototype" || key === "__proto__") {
|
|
break;
|
|
}
|
|
if (i < keys.length - 1) {
|
|
if (!target[key]) {
|
|
target[key] = {};
|
|
}
|
|
target = target[key];
|
|
} else {
|
|
target[key] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
for_set(req.query.path, req.query.val); // Compliant
|
|
----
|
|
|
|
|
|
== Resources
|
|
|
|
* https://github.com/HoLyVieR/prototype-pollution-nsec18/blob/master/paper/JavaScript_prototype_pollution_attack_in_NodeJS.pdf[Prototype pollution attack in NodeJS application - Olivier Arteau]
|
|
* CWE - https://cwe.mitre.org/data/definitions/1321[CWE-1321 - Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')]
|
|
|