2023-05-03 11:06:20 +02:00
== Why is this an issue?
2021-04-28 16:49:39 +02:00
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]
2021-04-28 18:08:03 +02:00
2023-05-03 11:06:20 +02:00
=== Noncompliant code example
2021-04-28 16:49:39 +02:00
For merge functions:
2022-02-04 17:28:24 +01:00
[source,javascript]
2021-04-28 16:49:39 +02:00
----
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:
2022-02-04 17:28:24 +01:00
[source,javascript]
2021-04-28 16:49:39 +02:00
----
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
----
2021-04-28 18:08:03 +02:00
2023-05-03 11:06:20 +02:00
=== Compliant solution
2021-04-28 16:49:39 +02:00
For merge functions:
2022-02-04 17:28:24 +01:00
[source,javascript]
2021-04-28 16:49:39 +02:00
----
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:
2022-02-04 17:28:24 +01:00
[source,javascript]
2021-04-28 16:49:39 +02:00
----
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
----
2021-04-28 18:08:03 +02:00
2023-05-03 11:06:20 +02:00
== Resources
2021-04-28 16:49:39 +02:00
* 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]
2024-01-15 17:15:56 +01:00
* CWE - https://cwe.mitre.org/data/definitions/1321[CWE-1321 - Improperly Controlled Modification of Object Prototype Attributes ('Prototype Pollution')]
2021-04-28 18:08:03 +02:00