Inyección noSQL

En anteriores posts he hablado sobre las inyecciones SQL. Suele ser el primer ejemplo sobre seguridad informática que se le pone a un estudiante: ” ´ or 1 = 1 — a “

Sin embargo, esto solo sirve para servidores que utilicen bases de datos relacionales, como son MySQL, MSSQL, Oracle. En la última década han aparecido otro tipo de bases de datos: las bases de datos no relacionales, como Couch o MongoDB.

Este tipo de bases de datos se utiliza para guardar una gran cantidad de datos que no tienen relación entre sí, datos que no encajan en el típico modelo tabular de las bases de datos SQL, como pueden ser imágenes, videos, social media, etc.

Las queries que se hacen a este tipo de bases de datos noSQL son muy distintas a las queries SQL. Por tanto, intentar meter una comilla en un parámetro no funcionará en estos casos. Sin embargo, eso no implica que estén libres de inyecciones. En este post mostraré cómo y por qué funcionan las noSQL injection mediante pruebas de concepto. Todos los ejemplos se basan en el libro “The Hacker Playbook 3”.

Simple NoSQL Injection

Para poder realizar una noSQL injection, se tiene que cumplir que se envíe una query al servidor en forma de JSON, y que podamos manipularla utilizando comparadores NoSQL.

La equivalencia de comparadores en noSQL es la siguiente: > es $gt, < es $lt, >= es $gte, y <= es $lte.

El equivalente al [ ` or 1 = 1 — a ] de SQL sería [ {“$gt”:””} ]. Significa que el operador $gt es mayor que NULL. Como cualquier cosa es mayor que NULL, la query siempre devuelve TRUE. Se entenderá mejor en el siguiente ejemplo:

Si intentamos hacer login en un servidor que utiliza bases de datos no relacionales, la petición contendrá un JSON parecido a {“username”:”admin”,”password”:”admin”}

En el servidor, se enviará una query a la base de datos parecida a esta:

db.collection(collection).find({“username”:username,”password”:password}).limit(1)…

La inyección consiste en insertar como password el payload {“$gt”:””}, sentencia que siempre devuelve TRUE, por lo que permite el acceso directamente al usuario admin sin saber su contraseña:

Si no sabes cual es el nombre del usuario administrador, sigue siendo posible acceder con su cuenta. Lo que hay que hacer es indicar en username el payload “username”:{“$gt”:”aaa”}. De esa forma, accederás con el primer usuario de la tabla cuyo nombre sea mayor que “aaa”. Tendrás que probar nombre por nombre, hasta encontrar la cuenta de usuario administrador:

Otros aspectos a tener en cuenta

Los nuevos frameworks y lenguajes pueden hacer que surjan oportunidades de inyección noSQL. Por ejemplo, Node.js, un modelo de servidor basado en javascript que se ha hecho muy popular recientemente, tiene un módulo llamado qs que permite convertir los parámetros de las peticiones HTTP en objetos JSON.

Una petición del estilo username[valor]=admin&password[valor]=admin se convertiría a {“username”:{“valor”:”admin”},”password”:{“valor”:”admin”}}.

Si el programador no ha tenido en cuenta esta conversión automática y solo valida las peticiones JSON, podemos conseguir una noSQL injection enviando una petición http. Basta con modificar la petición que originalmente se envía en el login (username=admin&password=admin&submit=login) por lo siguiente:

Puedes encontrar más ejemplos de NoSQL injection en la página de OWASP.

Lethani

Deja una respuesta