Pregunta Comprender el símbolo de autenticidad de Rails


Estoy teniendo problemas con el token de autenticidad en Rails, como lo he hecho muchas veces.

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


877
2018-06-02 20:01


origen


Respuestas:


Lo que pasa

Cuando el usuario ve un formulario para crear, actualizar o destruir un recurso, la aplicación Rails crea un authenticity_token, 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, la solicitud puede continuar.

Por qué sucede

Como el token de autenticidad se almacena en la sesión, el cliente no puede conocer su valor. Esto evita que las personas envíen formularios a la 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 imagina que fuiste a usar el servicio B, y viste una imagen que te gusta, y presionaste la imagen para ver un tamaño mayor de ella. Ahora, si hay algún código malvado en el servicio B, podría enviar una solicitud al servicio A (que está conectado), y solicitar eliminar su cuenta, enviando una solicitud a http://serviceA.com/close_account. Esto es lo que se conoce como CSRF (falsificación de solicitudes entre sitios).

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.

Documentos de la API describe detalles sobre la metaetiqueta:

La protección CSRF está activada con protect_from_forgery método,   que verifica el token y restablece la sesión si no coincide con   era de esperarse. Se genera una llamada a este método para nuevos Rails   aplicaciones por defecto.   El parámetro token se llama authenticity_token por defecto. El nombre   y el valor de este token debe agregarse a cada diseño que renderiza   formularios al incluir csrf_meta_tags en el encabezado de HTML

Notas

Tenga en cuenta que Rails solo verifica no los métodos idempotentes (POST, PUT / PATCH y DELETE). La solicitud GET no se verifica para el token de autenticidad. ¿Por qué? porque la especificación HTTP establece que las solicitudes GET son idempotentes y deberían no 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).

Además, la implementación real es un poco más complicada, como se definió al principio, lo que garantiza una mayor seguridad. Rails no emite el mismo token almacenado con cada forma. 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 procesa una página. Ver request_forgery_protection.rb.

Lecciones

Utilizar 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 pueda potencialmente modificar recursos en el servidor.


EDITAR: Comprobar el comentario de @erturne con respecto a las solicitudes GET siendo idempotentes. Él lo explica de una mejor manera que lo he hecho aquí.


1371
2017-10-15 11: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 saber, lo que ayuda a prevenir ataques de falsificación de solicitudes entre sitios.

Si simplemente tiene dificultades con los raíles que niegan su acceso de script AJAX, puede usar

<%= form_authenticity_token %>

para generar el token correcto cuando estás creando tu formulario.

Puedes leer más sobre esto en el documentación.


129
2018-06-02 20:16



¿Qué es CSRF?

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

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

Guión:

  • Visite el sitio de su banco, inicie sesión.
  • Luego, visite el sitio del atacante (por ejemplo, anuncio patrocinado de una organización que no es de confianza).
  • 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 ha llenado previamente los campos del formulario para transferir dinero de su cuenta a la cuenta del atacante.
  • La página del atacante incluye Javascript que envía un formulario a su banco.
  • Cuando se envía el formulario, el navegador incluye sus cookies para el sitio del banco, incluido el token de la 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 llama Falsificación de solicitudes entre sitios (CSRF).

Solución CSRF:

  • El servidor puede marcar formularios que provienen del 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).
  • El servidor proporciona un token válido en los formularios de sus páginas.
  • El servidor comprueba el token cuando se publica el formulario, rechaza los formularios sin el token adecuado.
  • Token de ejemplo: identificador de sesión cifrado con la clave secreta del servidor.
  • Rails genera automáticamente tales tokens: mira el campo de entrada de autenticidad_token en cada forma.

77
2018-06-13 01:54



Ejemplo de ataque mínimo que se evitaría

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

Es ahí donde entra en juego el token de CSRF:

  • 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

Entonces, 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 authenticity_token parámetro, y no hay forma de que lo haya adivinado, ya que es un gran número aleatorio.

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

El patrón de token sincronizador funciona debido a La misma política de origen: si pudiera hacer una solicitud XHR GET a su banco desde evil.com, y lea el resultado, podría leer un token y luego realizar la solicitud más tarde. Ya lo he explicado más adelante en: https://security.stackexchange.com/a/72569/53321

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

Cómo Rails envía los tokens

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

Básicamente:

  • A los ayudantes de HTML les gusta form_tag agregue un campo oculto al formulario si no es un formulario GET

  • AJAX es tratado automáticamente por jquery-ujs, que lee la ficha del 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 caducados obsoletos.

Otros enfoques de prevención


36
2017-11-12 20:30



los Authenticity Token es el método de los carriles para evitar  'ataques de falsificación de solicitudes entre sitios (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
2018-06-02 20:17



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

 <%= token_tag nil %>

crear

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

en cualquier sitio


32
2017-08-01 05:12



Tenga en cuenta que el mecanismo del token de autenticidad puede generar condiciones de carrera si tiene varias solicitudes concurrentes del mismo cliente. En esta situación, su servidor puede generar múltiples tokens de autenticidad cuando debería haber solo 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 aquí: http://www.paulbutcher.com/2007/05/race-conditions-in-rails-sessions-and-how-to-fix-them/


25
2017-08-30 23:52



El token de autenticidad se usa para evitar 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:

enter image description here

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

enter image description here

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

¿Huh? ¿Quién es este tipo tratando de iniciar una transferencia? No es el propietario de la cuenta, eso es seguro.

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

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

Oh, ese es John Doe. Se registró 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 mi ayuda session_id galleta, estaría dorado.

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

Entonces, si un hacker pudiera obtener  para hacer la solicitud GET que transfiere dinero a su cuenta, tendría éxito. ¿Cómo podría engañarte para que lo hagas?  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 el navegador de los usuarios se encuentra con esa etiqueta de imagen, realizará 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 había iniciado sesión recientemente en bank.com... el session_id se establecerá una cookie, y el servidor pensará que el usuario debe transferir $ 1,000,000 a la cuenta 999999!

enter image description here

Bueno, simplemente 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 pared? ¿Qué sucede 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 verdad. Un formulario que envía una solicitud POST se puede generar dinámicamente. Aquí está el ejemplo del 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 tu ApplicationController tiene esto:

protect_from_forgery with: :exception

Esta:

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

Está compilado 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á segura la solicitud.

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

enter image description here

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


23
2018-04-14 04:33



Métodos donde authenticity_token es requerido

authenticity_token se requiere en caso de métodos idempotentes como publicar, poner y eliminar, porque los métodos de Idempotent están afectando a los datos.

Por qué es obligatorio

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


8
2018-02-26 11:13



¿Qué es un authentication_token?

Esta es una cadena aleatoria utilizada por la aplicación de rieles 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 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 con form_for tag, se agrega automáticamente un authentication_token, de lo contrario puede usar <%= csrf_meta_tag %>.


3
2017-07-22 02:02