ruby-on-rails - usar - ruby on rails tutorial español




Entendiendo el token de autenticidad de Rails (7)

Me estoy topando con algunos problemas relacionados con el token de autenticidad en Rails, como lo he hecho muchas veces.

Pero realmente no quiero solo resolver este problema y continuar. Realmente me gustaría entender el token de autenticidad. Bueno, mi pregunta es, ¿tiene alguna fuente completa de información sobre este tema o pasaría su tiempo para explicar en detalles aquí?


¿Qué es CSRF?

El token de autenticidad es una contramedida para la falsificación de solicitudes entre sitios (CSRF). ¿Qué es CSRF, te preguntarás?

Es una forma en la que un atacante puede potencialmente secuestrar sesiones sin siquiera conocer tokens de sesión.

Escenario :

  • Visite el sitio de su banco, inicie sesión.
  • Luego visite el sitio del atacante (por ejemplo, un anuncio patrocinado de una organización no confiable).
  • La página del atacante incluye un formulario con los mismos campos que el formulario "Transferir fondos" del banco.
  • El atacante conoce la información de su cuenta y tiene campos de formulario rellenados previamente para transferir dinero de su cuenta a la cuenta del atacante.
  • La página del atacante incluye Javascript que envía el formulario a su banco.
  • Cuando se envía el formulario, el navegador incluye sus cookies para el sitio del banco, incluido el token de sesión.
  • El banco transfiere dinero a la cuenta del atacante.
  • La forma puede estar en un iframe que es invisible, por lo que nunca se sabe que ocurrió el ataque.
  • Esto se denomina falsificación de solicitud entre sitios (CSRF).

Solución CSRF :

  • El servidor puede marcar los formularios que vinieron del propio servidor
  • Cada formulario debe contener un token de autenticación adicional como un campo oculto.
  • El token debe ser impredecible (el atacante no puede adivinarlo).
  • Servidor proporciona token válido en formularios en sus páginas.
  • El servidor comprueba el token cuando se publica el formulario, rechaza los formularios sin el token adecuado.
  • Ejemplo token: identificador de sesión cifrado con clave secreta del servidor.
  • Rails genera automáticamente dichos tokens: vea el campo de entrada authenticity_token en cada formulario.

El Authenticity Token es el método de Rails para prevent ataques de falsificación de solicitudes entre sitios (CSRF o XSRF) .

Para simplificarlo, se asegura de que las solicitudes PUT / POST / DELETE (métodos que pueden modificar el contenido) a su aplicación web se realicen desde el navegador del cliente y no desde un tercero (un atacante) que tenga acceso a una cookie creada. en el lado del cliente.


El token de autenticidad se usa para prevenir ataques de falsificación de solicitudes entre sitios (CSRF). Para comprender el token de autenticidad, primero debe comprender los ataques CSRF.

CSRF

Supongamos que usted es el autor de bank.com . Tiene un formulario en su sitio que se utiliza para transferir dinero a una cuenta diferente con una solicitud GET:

Un pirata informático podría simplemente enviar una solicitud HTTP al servidor que diga GET /transfer?amount=$1000000&account-to=999999 , ¿verdad?

Incorrecto. El ataque de los hackers no funcionará. El servidor básicamente pensará?

Eh ¿Quién es este chico tratando de iniciar una transferencia. No es el dueño de la cuenta, eso es seguro.

¿Cómo sabe esto el servidor? Porque no hay una cookie session_id autentique al solicitante.

Cuando inicia sesión con su nombre de usuario y contraseña, el servidor establece una cookie de session_id en su navegador. De esa manera, no tiene que autenticar cada solicitud con su nombre de usuario y contraseña. Cuando su navegador envía la cookie session_id , el servidor sabe:

Oh, ese es John Doe. Se ha registrado con éxito hace 2.5 minutos. Él es bueno para ir

Un hacker podría pensar:

Hmm Una solicitud HTTP normal no funcionará, pero si pudiera obtener esa cookie de session_id , estaría dorado.

El navegador de los usuarios tiene un conjunto de cookies para el dominio bank.com . Cada vez que el usuario realiza una solicitud al dominio bank.com , todas las cookies se envían. Incluyendo la cookie session_id .

Por lo tanto, si un pirata informático pudiera hacer que realices la solicitud GET que transfiere dinero a su cuenta, tendrá éxito. ¿Cómo podría engañarte para que lo hicieras? Con Cross Site Request Forgery.

Es bastante simple, en realidad. El hacker podría conseguir que visites su sitio web. En su sitio web, podría tener la siguiente etiqueta de imagen:

<img src="http://bank.com/transfer?amount=$1000000&account-to=999999">

Cuando el navegador de los usuarios encuentre esa etiqueta de imagen, hará una solicitud GET a esa URL. Y dado que la solicitud proviene de su navegador, le enviará todas las cookies asociadas con bank.com . Si el usuario ha bank.com recientemente en bank.com ... se bank.com la cookie session_id , y el servidor pensará que el usuario tenía la intención de transferir $ 1,000,000 a la cuenta 999999.

Bueno, no visites sitios peligrosos y estarás bien.

Eso no es suficiente. ¿Qué pasa si alguien publica esa imagen en Facebook y aparece en tu muro? ¿Qué sucede si se inyecta en un sitio que está visitando con un ataque XSS?

No es tan malo. Sólo las solicitudes GET son vulnerables.

No es verdad. Un formulario que envía una solicitud POST puede generarse dinámicamente. Aquí está el ejemplo de la Guía de Rails sobre Seguridad :

<a href="http://www.harmless.com/" onclick="
  var f = document.createElement('form');
  f.style.display = 'none';
  this.parentNode.appendChild(f);
  f.method = 'POST';
  f.action = 'http://www.example.com/account/destroy';
  f.submit();
  return false;">To the harmless survey</a>

Token de Autenticidad

Cuando su ApplicationController tiene esto:

protect_from_forgery with: :exception

Esta:

<%= form_tag do %>
  Form contents
<% end %>

Se compila en esto:

<form accept-charset="UTF-8" action="/" method="post">
  <input name="utf8" type="hidden" value="&#x2713;" />
  <input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />
  Form contents
</form>

En particular, se genera lo siguiente:

<input name="authenticity_token" type="hidden" value="J7CBxfHalt49OSHp27hblqK20c9PgwJ108nDHX/8Cts=" />

Para protegerse contra los ataques CSRF, si Rails no ve el token de autenticidad enviado junto con una solicitud, no considerará la solicitud como segura.

¿Cómo se supone que un atacante sabe qué es este token? Se genera aleatoriamente un valor diferente cada vez que se genera el formulario:

Un ataque de Cross Site Scripting (XSS): así es como. Pero esa es una vulnerabilidad diferente para un día diferente.


Tenga en cuenta que el mecanismo del token de autenticidad puede generar condiciones de carrera si tiene varias solicitudes simultáneas del mismo cliente. En esta situación, su servidor puede generar múltiples tokens de autenticidad cuando solo debería haber uno, y el cliente que recibe el token anterior en un formulario fallará en su próxima solicitud porque el token de cookie de sesión se ha sobrescrito. Hay un informe sobre este problema y una solución no completamente trivial aquí: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/


¿Qué es un identificador de autenticación?

Esta es una cadena aleatoria utilizada por la aplicación Rails para asegurarse de que el usuario está solicitando o realizando una acción desde la página de la aplicación, no desde otra aplicación o sitio.

¿Por qué es necesaria una autenticación?

Para proteger su aplicación o sitio de la falsificación de solicitudes entre sitios.

¿Cómo agregar un identificador de autenticación a un formulario?

Si está generando un formulario usando la etiqueta form_for, se agrega automáticamente un símbolo de autenticación; de lo contrario, puede usar <%= csrf_meta_tag %> .


Ejemplo de ataque mínimo que se evitaría.

En mi sitio web evil.com te convenzo para que envíes el siguiente formulario:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="to"      value="ciro"></p>
  <p><input type="hidden" name="ammount" value="100"></p>
  <p><button type="submit">CLICK TO GET PRIZE!!!</button></p>
</form>

Si ha iniciado sesión en su banco a través de cookies de sesión, entonces las cookies se enviarán y la transferencia se realizará sin que usted lo sepa.

Es decir, cuando el token CSRF entra en juego:

  • con la respuesta GET que devolvió el formulario, Rails envía un parámetro oculto aleatorio muy largo
  • cuando el navegador realiza la solicitud POST, enviará el parámetro y el servidor solo lo aceptará si coincide

Así que el formulario en un navegador auténtico se vería así:

<form action="http://bank.com/transfer" method="post">
  <p><input type="hidden" name="authenticity_token" value="j/DcoJ2VZvr7vdf8CHKsvjdlDbmiizaOb5B8DMALg6s=" ></p>
  <p><input type="hidden" name="to"                 value="ciro"></p>
  <p><input type="hidden" name="ammount"            value="100"></p>
  <p><button type="submit">Send 100$ to Ciro.</button></p>
</form>

Por lo tanto, mi ataque fallaría, ya que no estaba enviando el parámetro authenticity_token , y no hay forma de que pudiera adivinarlo ya que es un número aleatorio enorme.

Esta técnica de prevención se llama patrón de token de sincronizador .

El patrón de token del sincronizador funciona debido a la Política del mismo origen : si pudiera hacer una solicitud GET de XHR a su banco desde evil.com , y leer el resultado, podría leer un token y luego realizar la solicitud más adelante. He explicado esto más detalladamente en: https://security.stackexchange.com/a/72569/53321

Le recomiendo que lea la guía OWASP , sobre este y cualquier otro asunto de seguridad.

Cómo Rails envía los tokens.

Cubierto en: Rieles: ¿Cómo funciona csrf_meta_tag?

Básicamente:

  • Los ayudantes de HTML como form_tag agregan un campo oculto al formulario si no es un formulario GET

  • AJAX es tratado automáticamente por jquery-ujs , que lee el token de los meta elementos agregados a su encabezado por csrf_meta_tags (presente en la plantilla predeterminada), y lo agrega a cualquier solicitud realizada.

    uJS también intenta actualizar el token en formularios en fragmentos en caché desactualizados.

Otros enfoques de prevención.


Métodos donde se requiere authenticity_token

authenticity_token es obligatorio en el caso de métodos idempotentes como publicar, poner y eliminar, ya que los métodos idempotentes afectan a los datos.

Por qué se requiere

Se requiere para prevenir de las malas acciones. authenticity_token se almacena en una sesión, siempre que se crea un formulario en las páginas web para crear o actualizar los recursos, un token de autenticidad se almacena en un campo oculto y se envía con el formulario en el servidor. Antes de ejecutar la acción, el usuario autenticó el token autenticado se verifica en forma cruzada con el token authenticity_token almacenado en la sesión. Si authenticity_token es el mismo, entonces el proceso continúa, de lo contrario no realiza acciones.





authenticity-token