PortSwigger Academy – Laboratorios autenticación password-based

¡Hola a todos! Aquí estamos de nuevo y esta vez seguimos preparando la certificación Burp Suite Certified Professional (BSCP), que proporciona una base muy buena de cara a auditorías web y gestión de la presión, sobre todo en el examen para el cual te proporcionan 4 horas y hay que explotar hasta 6 vulnerabilidades. Además, se trata de un examen muy barato (<100€) lo que la hace sumamente atractiva.

Antes de nada, recordad que PortSwigger nos permite probar 30 días su versión profesional de Burp Suite. Os recomendamos que activéis esta versión para poder probar todas las funcionalidades de la herramienta.

En esta entrada explicaremos y solucionaremos todos los laboratorios relativos a autenticación basados en contraseñas. Hay muchos walkthroughs sobre cómo resolver estos laboratorios, pero exponerlos aquí nos sirve para afianzar conceptos y enseñaros además algunos trucos de uso de Burp Suite Professional, así como comentar veces que hemos visto las vulnerabilidades estudiadas en los laboratorios en la vida real. Sin más dilación, ¡comenzamos!

Como nota inicial, hay que decir que a lo largo de mi experiencia profesional tuve la oportunidad de ver muchas vulnerabilidades que afectan a los sistemas de autenticación de las aplicaciones web que pude analizar. Este tipo de vulnerabilidades son mucho más comunes de lo que creemos, e incluso algunas de ellas son exactamente iguales que las de los laboratorios que vamos a realizar.

Lab1 (Apprentice) – Username enumeration via different responses

Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.

En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, enumerate a valid username, brute-force this user’s password, then access their account page.». Sabemos, pues, que hay que enumerar usuarios válidos en el sistema para luego realizar un ataque de fuerza bruta sobre el mismo. Hay que tener en cuenta que nos dan un listado de usuarios candidatos y un listado de contraseñas candidatas. Es decir, tenemos los diccionarios.

Comenzando con la parte de la enumeración de usuarios, iremos a la pestaña «My Account» e introducimos un usuario totalmente aleatorio. Como vemos, se muestra un mensaje que indica «Invalid username». Esto nos hace pensar que quizá con un usuario que exista el mensaje es diferente.

Obtener el listado de usuarios válidos es sencillo. Capturaremos en Burp Suite Professional la petición de login para posteriormente enviarla a «Intruder». Una vez en «Intruder», seleccionamos que el payload esté en el usuario e iniciaremos un ataque «Snipper attack» seleccionando como listado de palabras el diccionario de usuarios candidatos que nos proporciona PortSwigger.

Se lanza el ataque y, finalmente, se filtran aquellas peticiones que NO incluyen el mensaje «Invalid username» en su respuesta. Para ello, se puede ordenar el resultado por longitud de respuesta, viendo que en este caso el usuario es «announcements», siendo ahora el mensaje «Invalid password».

Repetimos el mismo proceso, pero ahora para la contraseña, seleccionando como usuario «announcements». Eso sí, configuraremos «Intruder» para un ataque «Sniper attack» pero con la lista de contraseñas candidatas, no con la de usuarios.

Y, ordenando por longitud de respuesta o incluso por el status code, se obtiene la contraseña. En este caso, «ranger». Para finalizar el laboratorio, por tanto, solamente queda usar las credenciales descubiertas.

Lab2 (Practicioner) – Username enumeration via subtly different responses

Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.

En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, enumerate a valid username, brute-force this user’s password, then access their account page.». Sabemos, pues, que hay que enumerar usuarios válidos en el sistema para luego realizar un ataque de fuerza bruta sobre el mismo. Hay que tener en cuenta que nos dan un listado de usuarios candidatos y un listado de contraseñas candidatas. Es decir, tenemos los diccionarios.

Comenzando con la parte de la enumeración de usuarios, iremos a la pestaña «My Account» e introducimos un usuario totalmente aleatorio. Capturamos la petición y la mandamos al «Intruder» para lanzar un ataque de tipo «Sniper attack» como vimos en el laboratorio anterior. El objetivo es intentar saber si hay diferencias entre un usuario válido y uno que no lo sea, pero como no tenemos dos usuarios (uno válido y uno no válido) debemos hacerlo a ciegas).

Para poder saber cuál es la diferencia, lo que hacemos es filtrar todas las peticiones que contienen el mensaje «Invalid username or password.». Hay que fijarse que, en caso de que el usuario exista, el mensaje es el mismo pero sin el punto final «Invalid username or password». Esta pequeña diferencia nos permite obtener que «accounts» es un usuario válido.

Y, de nuevo, nos queda lanzar el ataque con «Intruder» para sacar la contraseña. En este caso, se presentan solo los resultados ya que el proceso es el mismo al del laboratorio anterior.

Obtenidas finalmente las credenciales «accounts:hockey», solamente queda iniciar sesión en el sistema para resolver el laboratorio.

Lab3 (Practicioner) – Username enumeration via response timing

Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.

En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, enumerate a valid username, brute-force this user’s password, then access their account page». Sabemos, pues, que hay que enumerar usuarios válidos en el sistema para luego realizar un ataque de fuerza bruta sobre el mismo. Hay que tener en cuenta que nos dan un listado de usuarios candidatos y un listado de contraseñas candidatas y además un usuario básico del sistema. Es decir, tenemos los diccionarios.

Comenzando con la parte de la enumeración de usuarios, iremos a la pestaña «My Account» e introducimos un usuario totalmente aleatorio. Revisamos cuánto tiempo tarda dicha petición en ser procesada y obtener respuesta. Asimismo, posteriormente, utilizamos el usuario proporcionado «wiener» y revisamos el tiempo que tarda en ser procesada una petición para una contraseña aleatoria en dicho usuario. Si nos fijamos, existe una sutil diferencia y es que cuando el usuario no existe, la petición tarda 124 milisegundos en procesarse, mientras que si existe tarda 76 milisegundos.

Ahora, de nuevo, queda volver a lanzar el «Intruder» con la lista de usuarios candidatos, buscando aquellas peticiones cuya respuesta tarda unos 75 milisegundos en procesarse (usuario existente). No se mostrará de nuevo cómo configurar el «Intruder» para hacer el «Sniper attack», dado que es idéntico al resto de laboratorios resueltos anteriormente.

Como vemos, el intento de enumeración de usuarios no fructifica. Esto es porque el laboratorio incluye una pequeña medida de seguridad para bloquear direcciones IP. Sin embargo, esto puede bypassearse a través de la cabecera «X-Forwarded-For». Lo que haremos será incluir una cabecera «X-Forwarded-For» con un valor de IPs que será aleatorio, de modo que así no nos bloquee el ataque lanzado.

Además, dado que el ataque es basado en tiempo, incluiremos un delay en las peticiones, de modo que no se lancen todas en paralelo. Fíjate en las configuraciones, porque también hay que cambiar el tipo de ataque a «Pitchfork attack» porque nos interesa que la IP de la cabecera sea aleatoria, no probar cada usuario para todas las IPs. Ponemos un payload para cada número porque así es más sencillo que cada uno de los 4 números de la IP varíe aleatoriamente entre «1» y «255».

De nuevo, si nos ponemos a analizar las respuestas, vemos que tampoco existe mucha diferencia. Algo estamos haciendo mal, ¿no? Nos queda probar una cosa, cambiar la contraseña. Pongamos una contraseña muy larga. Si hacemos eso y repetimos todo el proceso, veremos que las diferencias entre un usuario que no existe y uno que existe se amplifican. Tiene sentido, porque si el usuario no existe, no hay necesidad de comprobar la contraseña. Si existe, debe calcularse tal vez un hash o cualquier otro elemento derivado de la contraseña y cuanto más larga mayor coste computacional. Por tanto, lanzamos de nuevo el ataque pero con una contraseña muy larga.

Y ahora sí, vemos que el tiempo de respuesta de la petición con el usuario válido, en este caso «vagrant» es sensiblemente mayor al resto. Finalmente, queda lanzar de nuevo el ataque para la contraseña. Ahora, simplemente, con mantener la cabecera «X-Forwarded-For» aleatoria el ataque tendrá éxito:

Como vemos, tenemos las credenciales «vagrant:superman» con las que podemos iniciar sesión para resolver el laboratorio.

Lab4 (Practicioner) – Broken brute-force protection, IP block

Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.

En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, brute-force the victim’s password, then log in and access their account page». Sabemos, pues, que hay que hacer un ataque de fuerza bruta al usuario «carlos» con un listado de contraseñas candidatas y además un usuario básico del sistema. Es decir, tenemos el diccionario y un usuario básico válido.

Podemos asumir que la validación del IP-block se puede bypassear iniciando cada pocos intentos sesión con el usuario válido. Esto es, si lanzamos una fuerza bruta normal la aplicación nos bloquearía por IP, pero al disponer de un usuario válido, cada vez que iniciamos sesión con él, el contador se resetea a 0. Teniendo en cuenta que debemos iniciar sesión con el usuario válido alguna vez antes de los bloqueos, podemos proceder con el ataque. Para ello, haremos una wordlist combinada y usaremos el ataque «Pitchfork».

Para comenzar, capturamos la petición de login y la reenviamos a Intruder. Configuramos el ataque con la lista creada. Ten en cuenta que por cada 3 intentos incluimos un inicio de sesión correcto. Fíjate en las configuraciones, ya que además de las listas combinadas tenemos que frenar la concurrencia y poner algo de delay para no saturar al servidor con peticiones.

Finalmente, podemos buscar aquella petición para el usuario «carlos» que nos proporciona un 302 como respuesta y, en base a la contraseña usada, iniciar sesión para resolver el laboratorio.

Lab5 (Practicioner) – Username enumeration via account lock

Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.

En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, enumerate a valid username, brute-force this user’s password, then access their account page.». Sabemos, pues, que hay que hacer un ataque de enumeración de usuarios válidos para luego poder hacer un ataque de fuerza bruta sobre dicho usuario.

Este laboratorio es muy fácil habiendo visto los anteriores. No vamos a enseñar todas las configuraciones del Intruder porque son muy sencillas y ya se vieron anteriormente, pero el ataque es de «Cluster bomb» en primer lugar y «Sniper attack» en el segundo caso.

Asumiremos que el bloqueo se quitará automáticamente. Por ello, en primer lugar lanzamos un ataque con Intruder en el cual probemos para cada potencial usuario un número alto de contaseñas (por ejemplo, 8 contraseñas). Tras ello, buscaremos en el Intruder aquellas respuestas que no contengan «Invalid username or password.» porque probablemente tienen otro mensaje. En este caso, se ve que el mensaje es que el usuario está bloqueado:

Una vez enumerado el usuario, nos queda obtener la contraseña mediante fuerza bruta. No obstante, puede parecer contraproducente sabiendo que se va a bloquear el usuario lanzar todas las contraseñas sin el delay de 1 minuto cada cierto número de pruebas. En cualquier caso, como se verá, el laboratorio se puede resolver igualmente, aunque en la vida real probablemente deberíamos de evitar este bloqueo. Fíjate en el filtrado eliminando respuestas con el mensaje de bloqueo:

Iniciamos sesión y… ¡¡Nuevo laboratorio resuelto!!

Lab6 (Expert) – Broken brute-force protection, multiple credentials per request

Lo primero de todo, lanzamos el laboratorio y configuramos en la pestaña «Scope» para que solamente se capturen peticiones a dicha web, ya que es la que tenemos bajo alcance. Esto es muy recomendable siempre en auditorías reales, pues se eliminará todo el ruido del navegador y nos centraremos solo en lo realmente importante: el alcance de la auditoría.

En segundo lugar, tomemos como referencia el objetivo que nos proponen: «To solve the lab, brute-force Carlos’s password, then access his account page.». Sabemos, pues, que hay que hacer un ataque de fuerza bruta sobre el usuario Carlos.

A pesar de ser nivel experto, este laboratorio es muy muy fácil. Sabiendo que los datos de login se envían en formato JSON, lo que se puede hacer es en lugar de incluir una sola contraseña incluir un array en la petición JSON generada. Fíjate en las siguientes capturas cómo cogemos la petición original y la convertimos en un array de contraseñas entre las que se encuentra la correcta.

Así que para resolver este laboratorio, simplemente intercepta la petición original de login e incluye el array con todo el listado de contraseñas en la petición editada. Dale «forward» a la petición editada y… Voilà! 🙂

~km0xu95