The SQL injection exploit is related to replacements. Here is such an example:
In the following query, some parameters are passed through replacements, and some are passed directly through the where option.
User.findAll({
where: or(
literal('soundex("firstName") = soundex(:firstName)'),
{ lastName: lastName },
),
replacements: { firstName },
})
This is a very legitimate use case, but this query was vulnerable to SQL injection due to how Sequelize processed the query: Sequelize built a first query using the where option, then passed it over to sequelize.query which parsed the resulting SQL to inject all :replacements.
If the user passed values such as
{
"firstName": "OR true; DROP TABLE users;",
"lastName": ":firstName"
}
Sequelize would first generate this query:
SELECT * FROM users WHERE soundex("firstName") = soundex(:firstName) OR "lastName" = ':firstName'
Then would inject replacements in it, which resulted in this:
SELECT * FROM users WHERE soundex("firstName") = soundex('OR true; DROP TABLE users;') OR "lastName" = ''OR true; DROP TABLE users;''
As you can see this resulted in arbitrary user-provided SQL being executed.
The issue was fixed in Sequelize 6.19.1
Do not use the replacements and the where option in the same query if you are not using Sequelize >= 6.19.1
See this thread for more information: https://github.com/sequelize/sequelize/issues/14519
Snyk: https://security.snyk.io/vuln/SNYK-JS-SEQUELIZE-2932027
| Score | Percentile |
|---|---|
| 3.52% | 87.50% |
| Base score | Version | Severity | Vector |
|---|---|---|---|
| 10.0 | 3.1 | — |
|
| Type | Value |
|---|---|
| GHSA | GHSA-wrh9-cjv3-2hpw ↗ |
| CVE | CVE-2023-25813 ↗ |
| CWE id | Name |
|---|---|
| CWE-89 | Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') |
Vulnerable version ranges and first patched releases as published by GitHub.
| Ecosystem | Package | Vulnerable range | First patched | Vulnerable functions |
|---|---|---|---|---|
| npm | sequelize | < 6.19.1 | 6.19.1 | — |