Last tested: 24 Jul, 2018

sequelize vulnerabilities

Multi dialect ORM for Node.JS

View on npm

sequelize (latest)

Published 22 Jul, 2018

Known vulnerabilities0
Vulnerable paths0
Dependencies26

No known vulnerabilities in sequelize

Security wise, sequelize seems to be a safe package to use.
Over time, new vulnerabilities may be disclosed on sequelize and other packages. To easily find, fix and prevent such vulnerabilties, protect your repos with Snyk!

Vulnerable versions of sequelize

Fixed in 4.17.2

Regular Expression Denial of Service (ReDoS)

low severity

Detailed paths

  • Introduced through: sequelize@4.17.1 > validator@8.2.0

Overview

validator is a library of string validators and sanitizers.

Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) attacks. It used a regular expression (^\s*data:([a-z]+\/[a-z0-9\-\+]+(;[a-z\-]+=[a-z0-9\-]+)?)?(;base64)?,[a-z0-9!\$&',\(\)\*\+,;=\-\._~:@\/\?%\s]*\s*$) in order to validate Data URIs. This can cause an impact of about 10 seconds matching time for data 70K characters long.

Disclosure Timeline

  • Feb 15th, 2018 - Initial Disclosure to package owner
  • Feb 16th, 2018 - Initial Response from package owner
  • Feb 18th, 2018 - Fix issued
  • Feb 18th, 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:

  1. CCC
  2. CC+C
  3. C+CC
  4. 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 9.4.1 or higher.

References

Fixed in 4.1.0

Prototype Pollution

low severity

Detailed paths

  • Introduced through: sequelize@4.0.0-2 > lodash@4.15.0

Overview

lodash is a 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);

Remediation

Upgrade lodash to version 4.17.5 or higher.

References

Fixed in 3.23.6

SQL Injection via GeoJSON

high severity

Detailed paths

  • Introduced through: sequelize@3.23.5

Overview

sequelize versions prior to 3.23.6 are vulnerable to SQL injection via GeoJSON documents that contain a value with a single quote. GeoJSON is a format used for encoding a variety of geographic data structures in a standard JSON document. The vulnerability exists within GeoJSON documents using the function ST_GeomFromGeoJSON (for postgresql/postgis) and the function GeomFromText (for mysql).

Note that sequelize users who do not use these specific functions are not affected. For users who do use these functions, this vulnerability has a high impact and is easily expoited, hence its high severity classification.

Remediation

Upgrade to version 3.23.6 or greater.

References

Fixed in 3.23.2

Buffer Overflow

medium severity

Detailed paths

  • Introduced through: sequelize@3.23.1 > validator@4.9.0

Overview

validator is a library of string validators and sanitizers.

Affected versions of this package are vulnerable to Buffer Overflow. It used a regular expression (/^(?:[A-Z0-9+\/]{4})*(?:[A-Z0-9+\/]{2}==|[A-Z0-9+\/]{3}=|[A-Z0-9+\/]{4})$/i) in order to validate Base64 strings.

Remediation

Upgrade validator to version 5.0.0 or higher.

References

Fixed in 3.20.0

SQL Injection in IN statement

high severity

Detailed paths

  • Introduced through: sequelize@3.19.3

Overview

sequelize versions prior to 3.20.0 improperly escape arrays of strings bound to named parameters.

Remediation

Upgrade to version 3.20.0 or greater.

References

Fixed in 3.17.2

Remote Memory Exposure

medium severity

Detailed paths

  • Introduced through: sequelize@3.17.1

Overview

A potential memory disclosure vulnerability exists in sequelize versions prior to 3.17.2. A field of type DataTypes.BLOB can be used to expose sensitive information such as code, runtime memory and user data into the database.

Details

sequelize uses the Buffer type to represent DataTypes.BLOB. Initializing a Buffer 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 BLOB field in such manner will dump uninitialized memory into the database. The patch wraps Buffer field initialization in sequelize by converting a number value N to a string, initializing the Buffer with N in its ascii form.

Proof of concept

var Sequelize = require('sequelize');
var sequelize = new Sequelize('pastebin', null, null,
    { host: '127.0.0.1', dialect: 'postgres', });

var Task = sequelize.define('Pastebin', {
    title: Sequelize.STRING,
    content: Sequelize.BLOB,
  });

Task.create({
  title: 'title',
  content: 100,
}).then(function (task) {
  console.log(task.title);
  console.log(task.content); // will print out 100 bytes of previously used memory
});

Remediation

Upgrade sequelize to version >= 3.17.3

References

Fixed in 3.17.0

SQL Injection in order/limit

high severity

Detailed paths

  • Introduced through: sequelize@3.16.0

Overview

sequelize versions prior to 3.17.0 are vulnerable to SQL Injection attacks if untrusted user input is passed into the order or limit parameters.

Example

models.User.findAll({
  limit: '1; DELETE FROM "Users" WHERE 1=1; --',
}).then(function (users) {
  console.log(users);
});

Remediation

Upgrade to version 3.17.0 or greater.

References

Fixed in 3.12.1

SQL Injection

medium severity

Detailed paths

  • Introduced through: sequelize@3.12.0

Overview

sequelize is a multi dialect ORM for Node.JS/io.js. Affected versions of the package are vulnerable to SQL Injection via the user search by typing the name they want to search for and the application then executes:

User.findAll( { where: { name: req.body.name } } )

a malicious attacker may exploit this to find the users password by entering $password$. This could be avoided by specifying the exact column to search: the user column.

Remediation

Upgrade sequelize to version 3.12.1 or higher.

References

Fixed in 3.0.0

SQL Injection

medium severity

Detailed paths

  • Introduced through: sequelize@2.1.3

Overview

Beginning with sequelize version 3.0.0, two security related changes were introduced:

  • findOne no longer takes a string / integer / binary argument to represent a primaryKey. Use findById instead.
  • where: "raw query" is no longer legal, you must now explicitly use where: ["raw query", [replacements]]

Remediation

Upgrade to version 3.0.0 or greater.

References

Fixed in 2.0.6

Cross-site Scripting (XSS)

medium severity

Detailed paths

  • Introduced through: sequelize@2.0.5 > validator@3.22.2

Overview

validator is a library of string validators and sanitizers.

Affected versions of this package are vulnerable to Cross-site Scripting (XSS) in IE9 due to unescaped backticks.

Details

Cross-Site Scripting (XSS) attacks occur when an attacker tricks a user’s browser to execute malicious JavaScript code in the context of a victim’s domain. Such scripts can steal the user’s session cookies for the domain, scrape or modify its content, and perform or modify actions on the user’s behalf, actions typically blocked by the browser’s Same Origin Policy.

These attacks are possible by escaping the context of the web application and injecting malicious scripts in an otherwise trusted website. These scripts can introduce additional attributes (say, a "new" option in a dropdown list or a new link to a malicious site) and can potentially execute code on the clients side, unbeknown to the victim. This occurs when characters like \< > \" \' are not escaped properly.

There are a few types of XSS:

  • Persistent XSS is an attack in which the malicious code persists into the web app’s database.
  • Reflected XSS is an which the website echoes back a portion of the request. The attacker needs to trick the user into clicking a malicious link (for instance through a phishing email or malicious JS on another page), which triggers the XSS attack.
  • DOM-based XSS is an that occurs purely in the browser when client-side JavaScript echoes back a portion of the URL onto the page. DOM-Based XSS is notoriously hard to detect, as the server never gets a chance to see the attack taking place.

Remediation

Upgrade validator to version 3.35.0 or higher.

References

Fixed in 2.0.1

Regular Expression Denial of Service (ReDoS)

medium severity
  • Vulnerable module: moment
  • Introduced through: moment@2.8.4

Detailed paths

  • Introduced through: sequelize@2.0.0-rc8 > moment@2.8.4

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:

  1. CCC
  2. CC+C
  3. C+CC
  4. 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

Regular Expression Denial of Service (ReDoS)

low severity
  • Vulnerable module: moment
  • Introduced through: moment@2.8.4

Detailed paths

  • Introduced through: sequelize@2.0.0-rc8 > moment@2.8.4

Overview

moment is a lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.

An attacker can provide a long value to the duration 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).

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:

  1. CCC
  2. CC+C
  3. C+CC
  4. 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.11.2 or greater.

References

Regular Expression Denial of Service (ReDoS)

low severity
  • Vulnerable module: moment
  • Introduced through: moment@2.8.4

Detailed paths

  • Introduced through: sequelize@2.0.0-rc8 > moment@2.8.4

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) attacks. 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:

  1. CCC
  2. CC+C
  3. C+CC
  4. 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

Fixed in 2.0.0-rc8

SQL Injection in Order

high severity

Detailed paths

  • Introduced through: sequelize@2.0.0-rc7

Overview

sequelize versions prior to 2.0.0-rc7 are vulnerable to SQL Injection attacks if untrusted user input is passed into the order parameter.

Remediation

Upgrade to version 2.0.0-rc8 or greater.

References

Fixed in 2.0.0-rc3

SQL Injection

medium severity
  • Vulnerable module: sql
  • Introduced through: sql@0.39.0

Detailed paths

  • Introduced through: sequelize@2.0.0-rc2 > sql@0.39.0

Overview

sql is a sql string builder for node - supports PostgreSQL, mysql, Microsoft SQL Server, Oracle and sqlite dialects.

Affected versions of this package are vulnerable to SQL Injection. A malicious user may insert potentially user-controlled content into the queries without proper escaping, in cases where that is not verified additionally in the applications that are using sql library.

Remediation

There is no fix version for sql.

References

Regular Expression Denial of Service (DoS)

high severity

Detailed paths

  • Introduced through: sequelize@2.0.0-rc2 > validator@3.16.1

Overview

validator is a library of string validators and sanitizers.

Affected versions of this package are vulnerable to Regular Expression Denial of Service (ReDoS) attacks. It used a regular expression in order to validate URLs.

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:

  1. CCC
  2. CC+C
  3. C+CC
  4. 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

Update to version 3.22.1 or greater.

References

Fixed in 2.0.0-dev13

Regular Expression Denial of Service (ReDoS)

high severity

Detailed paths

  • Introduced through: sequelize@2.0.0-dev12 > underscore.string@2.3.3

Overview

underscore.string is a String manipulation helpers for javascript.

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:

  1. CCC
  2. CC+C
  3. C+CC
  4. 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

There is no fix version for underscore.string.

References

Fixed in 2.0.0-dev7

Cross-site Scripting (XSS)

medium severity

Detailed paths

  • Introduced through: sequelize@2.0.0-dev6 > validator@1.5.1

Overview

validator is a module for Node.js contains functionality meant to filter potential XSS attacks (a filter called xss). A method of bypassing the filter via an encoded URL has been publicly disclosed. In general, because the function’s filtering is blacklist-based it is likely that other bypasses will be discovered in the future. Developers are encouraged not to use the xss filter function in this package. The xss() function removes the word "javascript" when contained inside an attribute. However, it does not properly handle cases where characters have been hex-encoded. As a result, it is possible to build an input that bypasses the filter but which the browser will accept as valid JavaScript.

For example, browsers interpret abc as abc.

Details

Cross-Site Scripting (XSS) attacks occur when an attacker tricks a user’s browser to execute malicious JavaScript code in the context of a victim’s domain. Such scripts can steal the user’s session cookies for the domain, scrape or modify its content, and perform or modify actions on the user’s behalf, actions typically blocked by the browser’s Same Origin Policy.

These attacks are possible by escaping the context of the web application and injecting malicious scripts in an otherwise trusted website. These scripts can introduce additional attributes (say, a "new" option in a dropdown list or a new link to a malicious site) and can potentially execute code on the clients side, unbeknown to the victim. This occurs when characters like \< > \" \' are not escaped properly.

There are a few types of XSS:

  • Persistent XSS is an attack in which the malicious code persists into the web app’s database.
  • Reflected XSS is an which the website echoes back a portion of the request. The attacker needs to trick the user into clicking a malicious link (for instance through a phishing email or malicious JS on another page), which triggers the XSS attack.
  • DOM-based XSS is an that occurs purely in the browser when client-side JavaScript echoes back a portion of the URL onto the page. DOM-Based XSS is notoriously hard to detect, as the server never gets a chance to see the attack taking place.

Remediation

Upgrade to the latest version of this library. However, it should be noted that the fix for this vulnerability was to remove the xss filter functionality. Seek another library to provide proper output encoding.

References

-GitHub Issue

Fixed in 1.7.0-alpha3

SQL Injection

medium severity

Detailed paths

  • Introduced through: sequelize@1.7.0-alpha2

Overview

sequelize versions prior to 1.7.0-alpha3 are vulnerable to SQL Injection attacks if untrusted user input is passed into the order parameter.

Remediation

Upgrade to version 1.7.0-alpha3 or greater.

References

Fixed in 1.7.0-alpha2

Cross-site Scripting (XSS)

medium severity

Detailed paths

  • Introduced through: sequelize@1.7.0-alpha1 > validator@0.4.28

Overview

The validator module for Node.js contains functionality meant to filter potential XSS attacks (a filter called xss). Several ways to bypass the filter were discovered. In general, because the function’s filtering is blacklist-based it is likely that other bypasses will be discovered in the future. Developers are encouraged not to use the xss filter function in this package.

Source: Node Security Project

Details

Various inputs that could bypass the filter were discovered:

Improper parsing of nested tags:

<s <onmouseover="alert(1)"> <;s onmouseover="alert(1)">This is a test</s>

Incomplete filtering of javascript: URIs:

<a href="javascriptJ a V a S c R iPt::alert(1)" "<s>">test</a>

UI Redressing:

<div style="z-index: 9999999; background-color: green; width: 100%; height: 100%">
<h1>You have won</h1>Please click the link and enter your login details:
<a href="http://example.com/">http://good.com</a>
</div>

Bypass via Nested Forbidden Strings:

<scrRedirecRedirect 302t 302ipt type="text/javascript">prompt(1);</scrRedirecRedirect 302t 302ipt>

Additional bypasses were discovered by Krzysztof Kotowicz in 2012 when auditing CodeIgniter's XSS filtering function, which this code was based off of.

Details

Cross-Site Scripting (XSS) attacks occur when an attacker tricks a user’s browser to execute malicious JavaScript code in the context of a victim’s domain. Such scripts can steal the user’s session cookies for the domain, scrape or modify its content, and perform or modify actions on the user’s behalf, actions typically blocked by the browser’s Same Origin Policy.

These attacks are possible by escaping the context of the web application and injecting malicious scripts in an otherwise trusted website. These scripts can introduce additional attributes (say, a "new" option in a dropdown list or a new link to a malicious site) and can potentially execute code on the clients side, unbeknown to the victim. This occurs when characters like \< > \" \' are not escaped properly.

There are a few types of XSS:

  • Persistent XSS is an attack in which the malicious code persists into the web app’s database.
  • Reflected XSS is an which the website echoes back a portion of the request. The attacker needs to trick the user into clicking a malicious link (for instance through a phishing email or malicious JS on another page), which triggers the XSS attack.
  • DOM-based XSS is an that occurs purely in the browser when client-side JavaScript echoes back a portion of the URL onto the page. DOM-Based XSS is notoriously hard to detect, as the server never gets a chance to see the attack taking place.

Remediation

If you are a developer currently using the xss filter function from the validator package, you should consider replacing it with the escape filter function from the same package. This function replaces all instances of angle brackets (<, >), ampersands, and quotation marks, so no HTML tags will be processed.

References

Fixed in 1.7.0

Uninitialized Memory Exposure

low severity
  • Vulnerable module: mysql
  • Introduced through: mysql@2.0.1

Detailed paths

  • Introduced through: sequelize@1.6.0-beta-3 > mysql@2.0.1

Overview

mysql is a node.js driver for mysql.

Affected versions of the package are vulnerable due to the unsafe use of the Buffer() method. Uninitialized memory may be exposed when a value of type number is provided to various methods in mysql which require allocation of buffers and results in concatenation of uninitialized memory to the buffer collection.

This vulnerability is unlikely to be exploited, but may be possible if a server-side mysql accepts typed input for passwords from the client even though the user doesn’t control the server-side code (i.e through JSON format).

Details

Constructing a Buffer class with integer N creates a Buffer of length N with raw (not "zero-ed") memory.

In the following example, the first call would allocate 100 bytes of memory, while the second example will allocate the memory needed for the string "100":

// uninitialized Buffer of length 100
x = new Buffer(100);
// initialized Buffer with value of '100'
x = new Buffer('100');

You can read more about the insecure Buffer behavior on our blog.

Similar vulnerabilities were discovered in request, mongoose, ws and sequelize.

Remediation

Upgrade mysql to version 2.14.0 or higher. Note This is vulnerable only for Node <=4

References

Unauthorized SSL Connection due to lack of cert authentication

medium severity
  • Vulnerable module: mysql
  • Introduced through: mysql@2.0.1

Detailed paths

  • Introduced through: sequelize@1.6.0-beta-3 > mysql@2.0.1

Overview

mysql is a node.js driver for mysql. Affected versions of this package do not validate that the remote server has a trusted SSL certificate or not, making it easier for attackers to gain access to the MySQL Server.

Remediation

Upgrade mysql to version 2.3.0 or higher.

References