Ir al contenido principal

Prevención de ataques de inyección SQL/nosql en MongoDB

Protege MongoDB contra inyecciones nosql validando las entradas, protegiendo las consultas y utilizando defensas en profundidad. Aprende los patrones de ataque y cómo prevenirlos en esta guía.
Actualizado 12 sept 2025  · 6 min de lectura

Las aplicaciones MongoDB se enfrentan a graves riesgos de seguridad cuando no se valida la información introducida por los usuarios. Los ataques de inyección nosql pueden violar silenciosamente tu base de datos, exponiendo datos confidenciales y comprometiendo la integridad del sistema. Esta guía muestra estrategias defensivas probadas para sanitizar entradas, proteger consultas a bases de datos y crear una protección sólida contra amenazas basadas en inyecciones.

¿Qué es la inyección nosql?

La inyección nosql se produce cuando los atacantes aprovechan entradas de usuario insuficientemente validadas para manipular la lógica de consulta de la base de datos. Al inyectar cargas maliciosas, los atacantes pueden eludir los mecanismos de autenticación, extraer datos no autorizados o burlar los controles de seguridad de las aplicaciones.

A diferencia de la inyección SQL, que aprovecha las vulnerabilidades en la construcción de consultas basadas en cadenas, la inyección nosql aprovecha las estructuras de datos flexibles y las consultas dinámicas. Esto resulta especialmente peligroso cuando las aplicaciones aceptan entradas de tipado flexible, como interface{} o map[string]interface{} sin una validación adecuada.

Por qué MongoDB es diferente

Las consultas de MongoDB se crean utilizando objetos BSON (JSON binario), pares clave-valor estructurados, en lugar de cadenas sin formato. Este diseño evita muchos de los riesgos tradicionales de inyección, ya que las consultas no se ensamblan mediante la concatenación de cadenas.

Sin embargo, si la entrada del usuario se incrusta directamente en estos objetos BSON sin la validación adecuada, los atacantes pueden inyectar operadores MongoDB como $ne, $gto $or para cambiar la lógica de la consulta.

Ejemplo: inyección de operadores en Go

filter := bson.M{"name": inputName}
collection.Find(ctx, filter)

Si inputName es una cadena simple como «Joe», es seguro. Pero si tu código permite map[string]interface{} o JSON sin procesar, un atacante podría inyectar objetos operadores como:

{ "$ne": null }

Esta carga útil transforma la lógica de la consulta, haciendo coincidir cualquier documento en el que aparezca el nombre en lugar de filtrar por un valor específico, lo que elude eficazmente los controles de acceso previstos por la aplicación.

Reconocer patrones inseguros y errores comunes

1. Confianza implícita en los cuerpos de las solicitudes

El análisis directo de los cuerpos de las solicitudes en mapas BSON crea una vía de inyección en la que los atacantes pueden incrustar operadores de consulta maliciosos y construcciones lógicas complejas directamente en las operaciones de la base de datos.

// Unsafe
var filter bson.M
_ = json.NewDecoder(req.Body).Decode(&filter)

En su lugar, analiza solo los campos y tipos conocidos:

type QueryInput struct {
    Name string json:"name" validate:"required"
}

2. Aceptar tipos flexibles

Las vulnerabilidades de inyección suelen surgir cuando las API aceptan tipos de datos demasiado permisivos, como interface{} o mapas genéricos. Estas estructuras flexibles pueden albergar operadores MongoDB incrustados o construcciones de objetos maliciosos que eluden la lógica de consulta prevista.

Minimiza el uso de amarres sueltos a menos que sea absolutamente esencial e implementa una validación estricta cuando sea inevitable. En su lugar, define estructuras de datos explícitas que coincidan con el formato de entrada esperado y restrinjan los valores aceptables.

3. JSON en cadenas de consulta u operadores de consulta

Las API que exponen capacidades de filtrado dinámico a través de parámetros de consulta de URL o puntos finales de búsqueda presentan superficies de ataque atractivas. Los atacantes suelen atacar estas interfaces incrustando operadores codificados en JSON y lógica condicional directamente en las cadenas de consulta. Esto transforma los parámetros de filtro legítimos en operaciones maliciosas en la base de datos:

GET /search?filter={"price":{"$gt":0}}

Sin una validación rigurosa de los datos introducidos, este enfoque permite a los atacantes manipular las estructuras de las consultas y eludir los controles de seguridad, lo que podría exponer datos no autorizados o ampliar los privilegios más allá de los niveles de acceso previstos.

Mitigación:

  • Implementa listas de permitidos de campos y operadores para restringir los parámetros de consulta a valores predefinidos y seguros.
  • Envuelve explícitamente todos los valores proporcionados por el usuario en operadores $eq al crear filtros de base de datos para evitar la inyección de operadores alternativos.

4. Ampliación de consultas lógicas con inyección

Aplicaciones que permiten al usuario controlar operadores lógicos como $or crean oportunidades para ataques de expansión de consultas. Los atacantes pueden inyectar expresiones condicionales adicionales en estos operadores, alterando fundamentalmente la semántica de la consulta y potencialmente eludiendo las comprobaciones de autenticación o las restricciones de acceso a los datos. 

filter := bson.M{
  "$or": []bson.M{
    {"role": "user"},
    {"active": true},
  },
}

Si la entrada del usuario manipula directamente el cláusula $or , los atacantes pueden inyectar una condición no autorizada:

{ "$or": [ {"role": "user"}, {"active": true}, {"isAdmin": true} ] }

Esta consulta modificada podría eludir los controles de acceso basados en roles, lo que podría exponer datos administrativos o conceder privilegios elevados a usuarios no autorizados. Evita la modificación dinámica de los operadores lógicos mediante la implementación de una validación estricta de las entradas y evitando el control directo de los usuarios sobre la estructura de las consultas. 

GET /search?filter={"price":{"$gt":0}}

Sin una validación rigurosa de las entradas, este enfoque permite a los atacantes manipular las estructuras de consulta y eludir los controles de seguridad, lo que podría exponer datos no autorizados. 

Mitigación:

  • Implementa listas de permitidos para los campos y operadores autorizados, rechazando cualquier parámetro de consulta que se salga de estos límites predefinidos.
  • Aplica la coincidencia explícita de igualdad envolviendo todas las entradas del usuario en $eq para evitar la sustitución de operadores lógicos o de comparación.

Características de ejecución de JavaScript

MongoDB ofrece varias capacidades de ejecución de JavaScript del lado del servidor que introducen posibles riesgos de seguridad, entre los que se incluyen:

Estas características suponen un riesgo significativo para la seguridad y deben evitarse, salvo que sea imprescindible su uso por motivos críticos para la empresa. Para evitar la explotación, desactiva los scripts en la configuración de MongoDB:

Para mongod:

--noscripting

O a través del archivo de configuración:

security:
  javascriptEnabled: false

Aplica la misma configuración a los mongos en una implementación fragmentada.

Los operadores de consulta nativos de MongoDB proporcionan una funcionalidad completa que elimina la necesidad de ejecutar JavaScript en prácticamente todos los casos de uso. Evita por completo las cláusulas$where de a menos que mantengas un control absoluto sobre la validación de entradas y el contexto de ejecución.

Cómo prevenir la inyección nosql

1. Validar rigurosamente las entradas.

Implementa una validación de tipos estricta que solo acepte los tipos de datos primitivos esperados, como cadenas, enteros o booleanos. Rechaza cualquier objeto anidado, arreglo o nombre de campo no reconocido que pueda contener operaciones incrustadas o construcciones maliciosas.

type LoginInput struct {
    Username string json:"username" validate:"required,alphanum"
    Password string json:"password" validate:"required,min=8"
}

2. No confíes en la estructura de las consultas de los usuarios.

Construye todas las consultas de bases de datos utilizando asignaciones de campos predefinidas y controladas por la aplicación, así como plantillas de consulta. Prohibir que las entradas de los usuarios influyan en la arquitectura de las consultas, los operadores lógicos o las estructuras condicionales que podrían alterar los patrones de acceso a los datos previstos.

filter := bson.M{
    "username": input.Username,
    "password": input.Password,
}

Evita:

// Dangerous: allows injection of operators
_ = json.NewDecoder(req.Body).Decode(&filter)

La mayoría de los controladores de MongoDB proporcionan generadores de consultas fuertemente tipados que imponen una construcción estructurada de las consultas y evitan vulnerabilidades por inyección accidental. Aprovecha estas interfaces nativas en lugar de exponer mapas de consultas sin procesar u objetos BSON a través de los puntos finales de la aplicación.

filter := bson.M{
    "username": input.Username,
    "password": input.Password,
}

Evita:

// Dangerous: allows injection of operators
_ = json.NewDecoder(req.Body).Decode(&filter)

3. Inyección en bloque de operadores MongoDB

Evita que las entradas controladas por el usuario funcionen como operadores de consulta o construcciones lógicas. Tratad todos los datos de usuario como valores literales en lugar de componentes de consulta ejecutables.

En lugar de:

filter := bson.M{
    "status": input.Status,
}

Uso:

filter := bson.M{
    "status": bson.M{"$eq": input.Status},
}

Este enfoque impone una coincidencia estricta de igualdad y evita la ejecución de operadores inyectados como $ne, $ino $regex u otros modificadores lógicos que podrían eludir la lógica de consulta prevista.

4. Utilizar el mínimo privilegio para los usuarios de la base de datos.

Configura las conexiones a la base de datos de la aplicación con cuentas de usuario que solo tengan los permisos mínimos necesarios para las operaciones previstas. Evita utilizar credenciales de nivel administrativo en las configuraciones de las aplicaciones para prevenir posibles daños derivados de ataques de inyección exitosos.

5. Supervisar y probar

Implementa un registro exhaustivo para detectar patrones de consulta inusuales y establece protocolos de pruebas de seguridad periódicas. Valida la seguridad de los puntos finales intentando ataques de inyección con cargas malformadas, como:

{ "$ne": null }

Verifica que la aplicación lo rechaza.

Casos de prueba a tener en cuenta:

  • Objetos en lugar de cadenas: { «username»: { «$ne»: null } }
  • Arreglos en lugar de escalares: { «roles»: [ { «$gt»: «» } ] }
  • Operadores como valores de consulta: { «campo»: { «$regex»: «.*» } }

Lista de verificación resumida

  • Validación de entradas: Aplica tipos de datos estrictos, valida formatos y rechaza campos inesperados.
  • Construcción de consultas: Crea todas las consultas utilizando esquemas predefinidos y plantillas controladas por la aplicación.
  • Protección del operador: Bloquea los operadores MongoDB en las entradas de los usuarios envolviendo los valores en $eq o utilizando API tipadas.
  • JavaScript del lado del servidor: Elimina las cláusulas $where y desactiva la ejecución de JavaScript en las configuraciones de producción.
  • Control de acceso a la base de datos: Configura las conexiones de las aplicaciones con los permisos mínimos necesarios, evitando las credenciales administrativas.
  • Pruebas y supervisión: Realiza pruebas de inyección periódicas e implementa el registro de patrones de consulta anómalos.

Reflexiones finales

Las vulnerabilidades de inyección nosql se pueden prevenir por completo mediante prácticas de codificación seguras y disciplinadas. La implementación de una validación rigurosa de los datos introducidos, la construcción de consultas estructuradas y controles de seguridad de defensa en profundidad permite a los programadores mantener la flexibilidad y el rendimiento de las aplicaciones, al tiempo que se eliminan los vectores de ataque por inyección.

El éxito requiere comprender el flujo de datos completo de tu aplicación, desde el análisis de la solicitud inicial hasta la ejecución final de la consulta. Establece un enfoque de confianza cero para todas las fuentes de entrada, implementa la validación en los límites del sistema y prioriza los principios de programación defensiva en toda tu pila tecnológica.

Preguntas frecuentes

¿Por qué la inyección nosql supone un riesgo si MongoDB utiliza BSON en lugar de cadenas?

La inyección aún puede ocurrir antes de que se construya el objeto BSON. Si las entradas de los usuarios se analizan en tipos flexibles como map[string]interface{} o interface{} sin validación, los atacantes pueden inyectar operadores MongoDB como $ne o $or y manipular la lógica de las consultas.

¿Es seguro decodificar el cuerpo de una solicitud directamente en un bson.M o map[string]interface{}?

No. Esto permite a los usuarios inyectar operadores de consulta arbitrarios. Siempre asigna los datos de solicitud a tipos estrictos (por ejemplo, estructuras Go) y valida la entrada antes de crear consultas.

¿Qué problema hay en usar $where si la entrada está validada?

Incluso si la entrada se valida parcialmente, $where ejecuta JavaScript en el servidor. Cualquier error en la escapada o validación puede dar lugar a una inyección de código. Es más seguro evitar por completo $where o desactivar los scripts en la configuración de MongoDB.

¿Cómo puedo comprobar si tu punto final es vulnerable a la inyección nosql?

Intenta inyectar cargas útiles como:

{ "username": { "$ne": null } }

Si el punto final devuelve una respuesta válida o omite la lógica (por ejemplo, el inicio de sesión), la entrada no se valida ni se restringe correctamente.

¿Cuál es la mejor manera de crear consultas de forma segura en Go?

Utiliza estructuras tipadas para la entrada, evita la decodificación en mapas genéricos y envuelve los valores en $eq cuando sea necesario. Nunca permitas que el usuario defina operadores o introduzca partes de la consulta directamente.

Temas
Relacionado

blog

Contratos de datos desmitificados: Todo lo que necesitas saber

Lograr la escalabilidad en los sistemas de datos distribuidos y reducir los errores.
Mike Shakhomirov's photo

Mike Shakhomirov

11 min

blog

SQL Server, PostgreSQL, MySQL... ¿cuál es la diferencia? ¿Por dónde empiezo?

En este tutorial, aprenderás algunas de las diferencias básicas entre los dialectos SQL y por dónde deberías empezar.
Mona Khalil's photo

Mona Khalil

5 min

Tutorial

Base de datos Azure SQL: Configuración y gestión paso a paso

Aprende a crear, conectar, gestionar, consultar y proteger tu base de datos Azure SQL. Esta guía paso a paso cubre todo lo esencial para una configuración óptima de la base de datos.
Anneleen Rummens's photo

Anneleen Rummens

Tutorial

Introducción a los disparadores SQL: Guía para desarrolladores

Aprende a utilizar los disparadores SQL para automatizar tareas, mantener la integridad de los datos y mejorar el rendimiento de la base de datos. Prueba ejemplos prácticos como los comandos CREATE, ALTER y DROP en MySQL y Oracle.
Oluseye Jeremiah's photo

Oluseye Jeremiah

Tutorial

Ejemplos y tutoriales de consultas SQL

Si quiere iniciarse en SQL, nosotros le ayudamos. En este tutorial de SQL, le presentaremos las consultas SQL, una potente herramienta que nos permite trabajar con los datos almacenados en una base de datos. Verá cómo escribir consultas SQL, aprenderá sobre
Sejal Jaiswal's photo

Sejal Jaiswal

Tutorial

Cómo instalar y configurar MySQL en Docker

Aprende a instalar y configurar la base de datos MySQL dentro de contenedores Docker. El tutorial incluye conceptos como conectarse a servidores MySQL, ejecutar clientes MySQL para conectarse a contenedores, etc.
Bex Tuychiev's photo

Bex Tuychiev

Ver másVer más