flawopen.com/Referencia/Inyección NoSQL en MongoDB: cuando la entrada cambia la consulta
Inyección NoSQL en MongoDB: cuando la entrada cambia la consulta
MongoDB no ejecuta SQL, así que concatenar cadenas SQL no es el problema. Puede existir NoSQL Injection si la aplicación acepta un objeto anidado no confiable donde esperaba un valor escalar y lo pasa a un filtro MongoDB. Es un fallo de validación de entrada de la aplicación, no una CVE del servidor MongoDB.
En palabras sencillas: un valor se convierte en una regla
Imagina que un formulario pide un nombre, pero quien lo atiende acepta un conjunto completo de instrucciones en ese campo. La base de datos sigue las instrucciones en vez de comparar un nombre. Valida el tipo de valor esperado y construye tú la regla de búsqueda.
Límite de confianza: del JSON de la solicitud al filtro MongoDB
- Filtro de consulta
- Documento BSON que MongoDB interpreta como comparaciones de campos y, si están presentes, operadores de consulta.
- Inyección de operadores
- La aplicación recibe una estructura controlada por el usuario donde esperaba un único valor literal.
- Validación de escalares
- Comprobar tipo, longitud y formato permitido antes de que la entrada influya en una operación de base de datos.
- Proyección
- Lista de campos elegida por el servidor para limitar la exposición accidental de datos.
Cómo ocurre el fallo
El endpoint espera un escalar
El contrato de la API define username como una cadena, pero el analizador JSON también admite matrices, objetos, booleanos y null.
La aplicación omite la validación del tipo
El controlador inserta el valor analizado directamente en un filtro creado por el servidor; el objeto conserva su estructura de consulta en vez de ser una cadena literal.
MongoDB evalúa la estructura recibida
Si el documento anidado contiene operadores de consulta, el predicado puede diferir de la comparación exacta prevista. Los registros afectados dependen de la consulta y de las comprobaciones de autorización de la aplicación.
La respuesta determina la exposición
Los campos y la cantidad de registros devueltos dependen de la proyección, el endpoint y los privilegios de la cuenta de base de datos. Esto no demuestra por sí solo una omisión de autenticación ni acceso a toda la base de datos.
La documentación oficial de los drivers de MongoDB describe este límite cuando un endpoint convierte JSON sin validar en BSON y lo usa como filtro. Esta guía modela ese fallo de aplicación. No afirma que todas las instalaciones de MongoDB sean vulnerables, no identifica una CVE del servidor ni ofrece una receta para eludir la autenticación.
Patrones vulnerables y reforzados en Node.js
app.post("/users/lookup", async (req, res, next) => {
try {
// The route expects a string, but req.body.username is untrusted JSON.
const user = await users.findOne({ username: req.body.username });
res.json(user ? { username: user.username } : null);
} catch (error) {
next(error);
}
});
const loginSchema = z.object({
username: z.string().trim().min(1).max(128),
password: z.string().min(1).max(1024)
}).strict();
app.post("/login", async (req, res, next) => {
try {
const parsed = loginSchema.safeParse(req.body);
if (!parsed.success) return res.sendStatus(400);
const { username, password } = parsed.data;
// The application owns the filter key; input supplies only a string value.
const user = await users.findOne(
{ username },
{ projection: { _id: 1, username: 1, passwordHash: 1 } }
);
const passwordMatches = user &&
await argon2.verify(user.passwordHash, password);
if (!passwordMatches) return res.sendStatus(401);
return res.sendStatus(204); // Session creation is application-specific.
} catch (error) {
next(error);
}
});
El flujo reforzado rechaza los campos que no sean cadenas antes de acceder a la base de datos, no acepta filtros enviados por el cliente, construye en el código de la aplicación una clave fija para el filtro, devuelve solo los campos seleccionados y verifica el hash de la contraseña después de buscar al usuario. El ejemplo supone que z es Zod, users es la colección de MongoDB y argon2 es una biblioteca configurada para el hash de contraseñas; la creación de la sesión queda fuera del ejemplo.
Comprobaciones para verificar la corrección
- ✓Envía una cadena normal y confirma que el controlador consulta solo el campo exacto definido por la aplicación.
- ✓Envía un objeto, matriz, número, booleano, null, campo ausente, cadena demasiado larga y propiedad desconocida; verifica que el esquema rechaza formas inválidas antes de llamar a MongoDB.
- ✓Comprueba que la llamada a la base de datos recibe un filtro construido por el servidor, nunca un filtro del cliente ni un fragmento JSON sin procesar.
- ✓Verifica que la proyección excluye hashes de contraseñas y campos ajenos, y que el rol de base de datos tiene solo los permisos necesarios.
- ✓Almacena contraseñas con Argon2id o bcrypt y verifica el hash en la aplicación; nunca consultes MongoDB usando la contraseña enviada como filtro.
Fuentes primarias
- MongoDB — buenas prácticas de bibliotecas cliente: validar entradas antes de convertir JSON a BSON
- OWASP — guía de seguridad NoSQL
- MongoDB — crear un filtro de consulta (driver de C#): la validación es responsabilidad de la aplicación