Anatomía de un ataque XSRF

Un ataque Cross Site Request Forgery (CSRF) o falsificación de peticiones en sitios cruzados es un tipo de ataque que permite a un atacante engañar a una víctima forzándole a hacer una acción no legítima en una aplicación web. Crea una petición HTTP falsa y mediante el engaño, persuade a la víctima para que ejecute esa acción con sus credenciales.

Si la aplicación no contiene tokens no predecibles a la hora de enviar una acción o formulario, entonces es vulnerable a este tipo de ataques. Si además la víctima se encuentra autenticada en la aplicación en el momento de pinchar en el enlace malicioso, el ataque será exitoso.

Estos ataques suelen explotarse mediante ingeniería social, incitando a la víctima a pinchar en un enlace con una petición debidamente modificada para forzarle a ejecutar una acción concreta. Otra forma muy efectiva de explotar este tipo de vulnerabilidades es si además la aplicación es vulnerable a ataques de Cross Site Scripting almacenado. Si un atacante inyecta código javascript a la aplicación y que ese código fuerze a la víctima a realizar la acción, el ataque se ejecutará de forma automática sin intervención de la víctima.

Blablabla vamos con un ejemplo que seguramente se entenderá mejor que lo que he escrito hasta ahora ;)

Supongamos una aplicación web. En la sección de mi perfil de usuario puedo modificar mis datos, entre ellos mi contraseña. Cuando modifico la contraseña y envío el formulario, lo que se envía es una petición HTTP por POST, en este ejemplo con multipart con separador, pero es aplicable a cualquier formulario GET o POST.

POST /perfil/modificar HTTP/1.1
Host: www.vulnerableapp.com
Cookie: PHPSESSID=31c32c30d65a42313bb4abfe2dbe43c0;
[..] -----------------------------
Content-Disposition: form-data;
name="user" victima
-----------------------------
Content-Disposition: form-data;
name="email" victima@victima.com
-----------------------------
Content-Disposition: form-data;
name="password" asdf`

¿Que ocurriría si ahora me creo una página html especialmente creada, alojada en un servidor web ajeno a la web víctima, con este código?

<html>
  <body>
    <form action="http:/www.vulnerableapp.com/perfil/modificar" method="post" enctype="multipart/form-data"> <input type="hidden" name="user" value="victima" />
      <input type="hidden" name="email" value="atacante@atacante.com" />
      <input type="hidden" name="password" value="contraseñah4x0r" />
          </form>
    <script type="text/javascript">document.forms[0].submit(); </script>
   </body>
 </html>

Como podreis imaginar, estamos forzando a la víctima a cambiar la contraseña y el correo asociado de su cuenta, sin que se haya percatado. En una petición GET el código sería más sencillo incluso. Utilizando acortadores de urls se puede ocultar la verdadera dirección de la url maliciosa. Como hemos dicho antes, este ataque funciona cuando la víctima se encuentra autenticada en ese momento en la aplicación vulnerable. El navegador guarda la sesión y en cada petición envía la cookie para no tener que estar autenticándose cada vez, incluida la petición maliciosa.

OK entonces ¿Cómo se puede evitar estos ataques? La opción recomendada es incluir en cada petición HTTP un token aleatorio, de forma que el atacante no pueda forjar de antemano una petición HTTP. Este token ya iría incluido en el código HTML de cada enlace y el servidor web sería el encargado de comprobar que el token enviado junto con el formulario coincide con el que se le envió al cliente. La mayoría de frameworks ya incluyen módulos que implementan estas medidas. La web de OWASP incluye una excelente chuleta sobre como implementar medidas contra estos ataques.

Espero que os haya sido de utilidad este post. En próximos, más ataques :D

social