Exploiting NoSQL operator injection to extract unknown fields writeup

Descripción

The user lookup functionality for this lab is powered by a MongoDB NoSQL database. It is vulnerable to NoSQL injection.

To solve the lab, log in as carlos.

Tip: The password only uses lowercase letters.

Exploiting NoSQL operator injection to extract unknown fields writeup

Al entrar en el laboratorio encontraremos una tienda online:

Entraremos en el apartado ‘My account’ e intentaremos entrar con el usuario ‘carlos’, pero con cualquier contraseña. La petición que encontraremos en el logger será la siguiente:

Llevamos la petición al ‘Repeater’ y modificamos el JSON de la siguiente manera:

{"username":"carlos","password":{"$ne": "test"},"$where":"1"}

Esto hace lo siguiente:

  1. Envía como nombre de usuario a ‘carlos’.
  2. Como contraseña, indicamos que sea cualquiera excepto ‘test’.
  3. Por último, como la condición debe ser evaluada a ‘True’ para que el inicio de sesión sea exitoso, añadimos un ‘»$where»:»1″‘, que siempre es True, consiguiendo el acceso a la cuenta.

Ahora vemos que la cuenta está bloqueada y que necesita que reseteemos la contraseña. Con el objetivo de obtener el token para resetearla, vamos a explorar la base de datos para ver todos los campos que tiene y encontrar el campo que tenemos que ver. Nos llevamos la petición al ‘Intruder’ con Ctrl + I o Click derecho -> Send to Intruder. Allí modificamos el JSON de la siguiente manera:

{"username":"carlos","password":{"$ne": "test"},"$where":"Object.keys(this)[1].match('^.{§0§}§a§.*')"}

Con esto, en el operador ‘$where’ ejecutaremos un JavaScript que se encargue de lo siguiente:

  1. Object.keys(this): Recupera todos los campos del objeto de la base de datos.
  2. [1]: Empezando por el campo 1, dado que el campo 0 suele ser el id.
  3. .match(‘^.{§0§}§a§.*’): Si el carácter en el lugar §0§ equivale al carácter §a§ devuelve true.

Una vez finalice el ataque, ordenando las respuestas por el Payload 1 y por la longitud de estas, podremos ver los campos. En este caso el primero es ‘username’.

Nota: Es posible hacer esto con un tercer ‘§b§’, que se encargue de recorrer todos los campos, aunque se generan en total 7.000 peticiones para 10 posibles campos. Debido a que en este laboratorio sólo hay 4 campos es más rápido y menos invasivo subir esta valor manualmente.

Al hacerlo con el resto de campos encontraremos la siguiente información:

  1. _id
  2. username
  3. password
  4. email
  5. pwResetTkn

Nota: El campo número 5 (accedido con el índice 4), sólo aparecerá si entramos en «Forgot password?» e introducimos el usuario ‘carlos’. Si no, nos devolverá el código 500 en el ataque.

Ahora sabemos el nombre del campo, por lo que modificamos la petición del ‘Intruder’:

{"username":"carlos","password":{"$ne": "test"},"$where":"this.pwResetTkn.match('^.{§0§}§a§.*')"}

Nota: En este caso, la longitud del token es de 15, por lo que hay que modificar el ataque en ‘Payloads’:

Una vez finalizado, si ordenamos por orden ascendente el Payload 1 y la longitud encontraremos el token:

Copiamos este token manualmente, y nos lo llevamos a la petición del GET de ‘/forgot-password’.

Nota: Si no aparece esta petición en el logger, se puede conseguir refrescando la página que aparece al enviar el nombre de usuario, aunque esto generará un token nuevo y será necesario repetir la última parte del ataque en el ‘Intruder’.

Nota: Es importante no usar comillas al introducir el token nuevo en la URL.

Ahora, en la respuesta, damos Click derecho -> Show response in browser, que nos copiará en el portapapeles la URL. Vamos al navegador y accedemos para cambiar la contraseña de carlos:

Ahora podremos iniciar sesión en ‘My account’ con el usuario de ‘carlos’ y la contraseña que acabamos de introducir. Finalizando así el laboratorio:

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *