Comprender el token de Autenticidad de Rails


Me estoy topando con algunos problemas con respecto al Token de Autenticidad en Rails, como lo he hecho muchas veces ahora.

Pero realmente no quiero resolver este problema y seguir adelante. 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í?

Author: Andrei Eliade, 2009-06-03

10 answers

Lo que sucede

Cuando el usuario ve un formulario para crear, actualizar o destruir un recurso, la aplicación Rails crea un authenticity_token aleatorio, almacena este token en la sesión y lo coloca en un campo oculto en el formulario. Cuando el usuario envía el formulario, Rails busca el authenticity_token, lo compara con el almacenado en la sesión, y si coinciden con la solicitud se permite continuar.

Por Qué sucede

Dado que el token de autenticidad se almacena en la sesión, el cliente no puede saber su valor. Esto evita que las personas envíen formularios a una aplicación Rails sin ver el formulario dentro de esa aplicación. Imagine que está utilizando el servicio A, ha iniciado sesión en el servicio y todo está bien. Ahora imagine que fue a usar el servicio B, y vio una imagen que le gusta, y presionó en la imagen para ver un tamaño más grande de la misma. Ahora, si algún código maligno estaba allí en el servicio B, podría enviar una solicitud al servicio A (en el que está conectado), y pedir que elimine su cuenta, enviando una solicitud a http://serviceA.com/close_account. Esto es lo que se conoce como CSRF (Cross Site Request Forgery).

Si el servicio A está utilizando tokens de autenticidad, este vector de ataque ya no es aplicable, ya que la solicitud del servicio B no contendría el token de autenticidad correcto, y no se le permitirá continuar.

API docs describe los detalles acerca de meta tag:

La protección CSRF se activa con el método protect_from_forgery , que comprueba el token y restablece la sesión si no coincide con lo que era de esperar. Se genera una llamada a este método para nuevos Rails aplicaciones por defecto. El parámetro token se llama authenticity_token por defecto. Nombre y el valor de este token debe agregarse a cada diseño que renderice formularios mediante la inclusión de csrf_meta_tags en la cabecera HTML.

Notas

Tenga en cuenta que Rails solo verifica los métodos no idempotentes (POST, PUT/PATCH y DELETE). La solicitud GET no se comprueba para el token de autenticidad. ¿Por qué? porque la especificación HTTP indica que GET requests es idempotente y que no debe crear, alterar o destruir recursos en el servidor, y la solicitud debe ser idempotente (si ejecuta el mismo comando varias veces, debe obtener el mismo resultado cada vez).

También la implementación real es un poco más complicada como se definió al principio, lo que garantiza una mejor seguridad. Rails no emite el mismo token almacenado con cada formulario. Tampoco genera y almacena un token diferente cada vez. Genera y almacena un hash criptográfico en una sesión y emite nuevos tokens criptográficos, que se pueden comparar con el almacenado, cada vez que se renderiza una página. Véase request_forgery_protection.rb .

Lecciones

Use authenticity_token para proteger sus métodos no idempotentes (POST, PUT/PATCH y DELETE). También asegúrese de no permitir ninguna solicitud GET que potencialmente podría modificar los recursos en el servidor.


EDIT: Comprueba el comentario de @erturne sobre las peticiones GET siendo idempotentes. Él lo explica de una manera mejor que yo lo he hecho aquí.

 1378
Author: Faisal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-12 08:40:52

El token de autenticidad está diseñado para que sepa que su formulario se envía desde su sitio web. Se genera desde la máquina en la que se ejecuta con un identificador único que solo su máquina puede conocer, lo que ayuda a prevenir ataques de falsificación de solicitudes entre sitios.

Si simplemente tiene dificultades con rails negando el acceso a su script AJAX, puede usar

<%= form_authenticity_token %>

Para generar el token correcto cuando está creando su formulario.

Puedes leer más al respecto en la documentación .

 130
Author: Topher Fangio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-31 00:54:30

¿Qué es CSRF?

El Token de Autenticidad es una contramedida a la Falsificación de Solicitudes entre Sitios (CSRF). ¿Qué es CSRF?

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

Hipótesis :

  • 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 del banco Formulario de "Transferencia de fondos".
  • El atacante conoce la información de su cuenta y tiene campos de formulario precargados 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.
  • El formulario puede estar en un iframe que es invisible, por lo que nunca se sabe el el ataque ocurrió.
  • Esto se denomina Falsificación de Solicitudes de Sitios cruzados (CSRF).

Solución CSRF :

  • El servidor puede marcar formularios que provienen del propio servidor
  • Cada formulario debe contener un token de autenticación adicional como campo oculto.
  • El token debe ser impredecible (el atacante no puede adivinarlo).
  • El 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 token.
  • Token de ejemplo: identificador de sesión cifrado con clave secreta del servidor.
  • Rails genera automáticamente dichos tokens: consulte el campo de entrada authenticity_token en cada formulario.
 79
Author: Rose Perrone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-20 16:12:00

Ejemplo de ataque mínimo que se evitaría

En mi sitio web evil.com le convenzo de enviar 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, las cookies se enviarán y la transferencia se realizará sin que usted lo sepa.

Es decir, donde el token CSRF entra en juego:

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

Así que el formulario en un navegador authentic se vería como:

<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 manera de que pudiera haberlo adivinado ya que es un número aleatorio enorme.

Esta técnica de prevención se llama Patrón de Token Sincronizador.

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

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

Cómo Rails envía el fichas

Cubierto en: Rails: ¿Cómo Funciona csrf_meta_tag?

Básicamente:

  • Los ayudantes 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 elementos meta 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 obsoletos almacenados en caché.

Otros enfoques de prevención

 38
Author: Ciro Santilli 新疆改造中心 六四事件 法轮功,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:41

El Authenticity Token es el método de rails para prevenir 'ataques cross-site request forgery (CSRF o XSRF)' .

Para simplificar, 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.

 35
Author: andi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-02 20:17:18

Dado que Authenticity Token es tan importante, y en Rails 3.0 + puedes usar

 <%= token_tag nil %>

Para crear

<input name="authenticity_token" type="hidden" value="token_value">

En cualquier lugar

 32
Author: Yuan He,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-01 05:12:06

El token de autenticidad se usa para evitar ataques de Falsificación de Solicitudes entre Sitios (CSRF). Para entender el token de autenticidad, primero debe entender los ataques CSRF.

CSRF

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

introduzca la descripción de la imagen aquí

Un hacker podría enviar una solicitud HTTP al servidor diciendo GET /transfer?amount=$1000000&account-to=999999, ¿verdad?

introduzca la descripción de la imagen aquí

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

¿Eh? ¿Quién es este tipo 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 que autentique al solicitante.

Cuando inicia sesión con su nombre de usuario y contraseña, el servidor establece una cookie session_id en su navegador. De esa manera, no tienes para 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. Firmó con éxito hace 2,5 minutos. Está listo para irse.

Un hacker podría pensar:

Hmm. Una solicitud HTTP normal no funcionará, pero si pudiera poner mi mano en esa cookie session_id, estaría de oro.

El navegador del usuario tiene un montón de cookies configuradas 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.

Así que si un hacker pudiera conseguir que haga la solicitud GET que transfiere dinero a su cuenta, tendría éxito. ¿Cómo pudo engañarte para que lo hicieras? Con Cross Site Request Forgery.

Es bastante simple, en realidad. El hacker podría hacerte visitar 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 los usuarios el navegador se encuentra con esa etiqueta de imagen, hará una solicitud GET a esa url. Y dado que la solicitud proviene de su navegador, enviará con ella todas las cookies asociadas con bank.com. Si el usuario ha iniciado sesión recientemente en bank.com... la cookie session_id se establecerá, y el servidor pensará que el usuario quería transferir 1 1,000,000 a la cuenta 999999!

introduzca la descripción de la imagen aquí

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

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

No Es tan malo. Solo las solicitudes GET son vulnerables.

No es cierto. Un formulario que envía una solicitud POST se puede generar dinámicamente. Este es el ejemplo de la Guía 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

Esto:

<%= 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 ataques CSRF, si Rails no ve el token de autenticidad enviado junto con una solicitud, no considerará la solicitud segura.

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

introduzca la descripción de la imagen aquí

Una Cruz Ataque de script de sitio (XSS) - así es como. Pero esa es una vulnerabilidad diferente para un día diferente.

 27
Author: Adam Zerner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-23 21:37:48

Tenga en cuenta que el mecanismo del token de Autenticidad puede dar lugar a condiciones de carrera si tiene varias solicitudes simultáneas del mismo cliente. En esta situación, su servidor puede generar varios 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 escrito sobre este problema y una solución no del todo trivial aqui: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/

 25
Author: jdp,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-30 23:52:45

Métodos donde se requiere authenticity_token

authenticity_token se requiere en el caso de métodos idempotentes como post, put y delete, porque los métodos Idempotentes están afectando a los datos.

Por qué Se Requiere

Se requiere para prevenir de las acciones malas. authenticity_token se almacena en sesión, cada vez que se crea un formulario en páginas web para crear o actualizar recursos, se almacena un token de autenticidad en el campo oculto y se envía con el formulario en el servidor. Antes de ejecutar la acción user sent authenticity_token se verifica con authenticity_token almacenado en la sesión. Si authenticity_token es lo mismo entonces el proceso es continuar de lo contrario no realiza acciones.

 8
Author: uma,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-26 08:31:06

¿Qué es un authentication_token ?

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 necesario un authentication_token ?

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

Cómo agregar un authentication_token a un formulario ?

Si está generando un formulario usando la etiqueta form_for, authentication_token se añade automáticamente de lo contrario se puede utilizar <%= csrf_meta_tag %>.

 3
Author: Pradeep Sapkota,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-04 15:54:11