Inyección NoSQL: Entrar sin password

Fecha: 2026-10-27 21:09:41 Autor: Alex Rubio

A veces, para entrar en una cuenta no hace falta ni saber la contraseña. Basta con enviar un objeto donde el sistema esperaba un texto.

Todos imaginamos a un atacante probando contraseñas una tras otra hasta acertar. Pero existe una familia de fallos mucho más elegante y silenciosa, en la que el atacante no adivina nada: le pide directamente a la base de datos que le deje pasar. Y la base de datos, obediente, le abre la puerta.

Se llama inyección NoSQL. Es la prima menos conocida de la clásica inyección SQL, y afecta a muchas aplicaciones modernas que han cambiado las tablas de toda la vida por bases de datos como MongoDB. Vamos a ver cómo funciona y, sobre todo, cómo evitarla.

Por qué NoSQL cambia las reglas

Muchas aplicaciones ya no guardan sus datos en tablas SQL, sino en bases de datos documentales como MongoDB, que almacenan la información como objetos JSON. Cada usuario es un documento con sus campos: nombre de usuario, contraseña, rol, correo, y lo que haga falta.

Consultar esa base de datos también se hace con objetos. Para comprobar un login, la aplicación construye algo como "dame el documento cuyo usuario sea X y cuya contraseña sea Y". Y aquí está la clave: en MongoDB, esos criterios de búsqueda admiten operadores especiales, palabras que empiezan por el símbolo del dólar, como $ne (distinto de), $gt (mayor que) o $regex (coincide con esta expresión).

Esos operadores son perfectamente legítimos; forman parte del funcionamiento normal de la base de datos. El problema aparece cuando la entrada del usuario llega sin filtrar hasta la consulta. Si la aplicación espera un texto en el campo de contraseña, pero acepta sin rechistar un objeto, el atacante puede colar sus propios operadores dentro de la búsqueda. Es la misma idea de siempre en seguridad web: mezclar los datos del usuario con las instrucciones del programa.

El truco: entrar con un "distinto de"

Imagina un panel de login de lo más corriente y, por detrás, una base MongoDB con varios usuarios. Uno de ellos, al que llamaremos Luis, es una cuenta normal, con rol de usuario y sin privilegios.

Cuando Luis se identifica, la aplicación lanza una consulta del tipo: "busca el usuario Luis cuya contraseña sea Petito". Si interceptamos esa petición (algo que un auditor hace con un proxy como Burp Suite), vemos un usuario y una contraseña viajando como simples textos.

¿Y si la contraseña deja de ser un texto y se convierte en un operador? En lugar de enviar Petito, el atacante envía un objeto que, en la práctica, significa "cualquier contraseña distinta de un valor imposible". La consulta pasa a pedir: "dame el usuario Luis cuya contraseña sea distinta de un texto que sabemos que nadie usa".

Como la contraseña real de Luis, evidentemente, es distinta de ese valor inventado, la condición se cumple. La base de datos devuelve el usuario, y Luis entra sin saber su propia contraseña. No ha habido adivinación ni fuerza bruta: solo se ha cambiado la pregunta.

Peor aún: reconstruir la contraseña letra a letra

Entrar sin contraseña ya es grave, pero la misma debilidad permite algo más inquietante: averiguar la contraseña real, carácter a carácter, sin verla nunca.

La herramienta es el operador $regex, que comprueba si un texto encaja con un patrón. En lugar de preguntar por la contraseña entera, el atacante hace preguntas de sí o no:

  1. "¿La contraseña empieza por A?". El login responde que no (acceso denegado).
  2. Prueba con la B, la C… hasta que una letra hace que el login responda que sí. Ese es el primer carácter.
  3. Fija esa letra y repite la pregunta para la segunda posición, luego la tercera, y así sucesivamente.

Es un proceso automatizable y rapidísimo: el programa del atacante lanza miles de estas preguntas y va reconstruyendo la contraseña posición a posición, por ejemplo administrador123. Esta técnica se conoce como inyección a ciegas (blind), porque la aplicación nunca muestra la contraseña: solo su sí o su no van filtrando la respuesta.

Con la contraseña completa del administrador en la mano, ya no hace falta ningún truco. El atacante inicia sesión como admin por la puerta principal, y a partir de ahí controla la aplicación.

Conclusiones: el problema no es MongoDB

Es tentador culpar a la base de datos, pero MongoDB hace exactamente lo que se le pide. El fallo está en un error de diseño tan viejo como la web: confiar en lo que envía el usuario.

Tres ideas que conviene grabar a fuego:

  1. Los datos y las instrucciones no deben mezclarse. Es la misma raíz de la inyección SQL, de los ataques de scripts (XSS) y de tantos otros. Cuando la entrada del usuario puede convertirse en parte de la lógica de la consulta, has perdido el control.
  2. Un campo tiene un tipo, y hay que respetarlo. Una contraseña es texto, nunca un objeto. Si tu aplicación acepta un objeto donde esperaba una cadena, está aceptando órdenes disfrazadas de datos.
  3. "No tener SQL" no significa "no tener inyecciones". Cambiar de tecnología no elimina la clase de vulnerabilidad; solo cambia su forma. Cada motor trae sus propios operadores peligrosos.

Y hay un agravante: estos ataques no suelen dejar rastro evidente. No rompen nada, no lanzan errores llamativos. Para la aplicación, todo "funciona correctamente", igual que un cajero que entrega el dinero porque la pregunta estaba bien formulada.

Advertencias: cómo protegerse

La buena noticia es que defenderse de la inyección NoSQL es relativamente sencillo si se aplica desde el diseño. Estas son las medidas que recomendamos, en línea con las guías de INCIBE y OWASP:

  • Valida y tipa la entrada. Comprueba que cada campo es del tipo esperado. Si la contraseña debe ser texto, rechaza cualquier cosa que llegue como objeto o como array. Esta sola comprobación detiene la mayoría de estos ataques.
  • Rechaza operadores en los datos del usuario. No permitas que lleguen claves que empiecen por $ (como $ne o $regex) ni puntos en los nombres de campo dentro de la entrada del usuario.
  • Sanea siempre lo que envía el usuario. Usa las utilidades de limpieza de tu framework o librerías específicas (por ejemplo, un sanitizer para Express/Mongo) antes de construir cualquier consulta.
  • Usa consultas parametrizadas. Mantén separados los datos del usuario y la lógica de la consulta; no construyas búsquedas concatenando texto ni, mucho menos, evaluando JavaScript con la entrada dentro.
  • Aplica el mínimo privilegio. La cuenta que usa la aplicación contra la base de datos debe tener solo los permisos imprescindibles. Así, aunque alguien entre, el daño posible se limita.
  • Pon límites y vigila. Limita los intentos por IP y franja de tiempo para frenar la fuerza bruta a ciegas, y registra y monitoriza patrones anómalos (picos de consultas, muchas peticiones casi idénticas).
  • Mantén todo actualizado. Base de datos, drivers y dependencias: las versiones antiguas de MongoDB arrastraban fallos graves de inyección ya corregidos.

Y un consejo que vale su peso en oro: haz que alguien lo intente. Una auditoría de seguridad sobre tus formularios de acceso y tus APIs encuentra este tipo de agujeros antes de que lo haga un atacante.

Una última advertencia

Todo lo anterior se explica con un fin defensivo: entender el ataque es el primer paso para blindarse frente a él. Probar estas técnicas solo es legítimo en sistemas propios o con permiso por escrito del responsable. Hacerlo contra servicios ajenos es un delito, por mucho que la intención sea "demostrar que son vulnerables".

En Seoxan Tech auditamos aplicaciones web, APIs y bases de datos buscando exactamente esta clase de fallos: los que no rompen nada, no saltan en ningún antivirus y, sin embargo, abren la puerta de par en par. Si quieres saber si tus formularios de acceso resistirían un "distinto de", hablemos.


Fuentes

Comparte en tus redes sociales