Comprensión del token de autenticidad de Rails

Me estoy encontrando con algunos problemas con respecto al Token de autenticidad en Rails, como he tenido muchas veces.

Pero realmente no quiero 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 dedicaría su tiempo a explicar en detalle aquí?

preguntado el 02 de junio de 09 a las 20:06

Consulte también: "¿Por qué Google antepone mientras (1) a su respuesta JSON?" stackoverflow.com/questions/2669690/… -

10 Respuestas

Lo que sucede

Cuando el usuario ve un formulario para crear, actualizar o destruir un recurso, la aplicación Rails crea una 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 que sucede

Dado que 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 una aplicación Rails sin ver el formulario dentro de esa aplicación. Imagina que estás usando el servicio A, iniciaste sesión en el servicio y todo está bien. Ahora imagine que fue a utilizar el servicio B, vio una imagen que le gusta y presionó la imagen para verla en un tamaño más grande. Ahora, si había algún código maligno en el servicio B, podría enviar una solicitud al servicio A (en el que ha iniciado sesión) 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 solicitud entre sitios).

Si el servicio A usa 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 de Documentos describe los detalles sobre la metaetiqueta:

La protección CSRF se activa con el protect_from_forgery método, que verifica el token y restablece la sesión si no coincide con lo esperado. Se genera una llamada a este método para las nuevas aplicaciones de Rails de forma predeterminada. El parámetro del token se llama authenticity_token por defecto. El nombre y el valor de este token deben agregarse a cada diseño que representa formularios al incluir csrf_meta_tags en el encabezado HTML.

Notas

Tenga en cuenta que Rails solo verifica métodos no idempotentes (POST, PUT / PATCH y DELETE). No se comprueba la autenticidad de las solicitudes GET. ¿Por qué? porque la especificación HTTP establece que las solicitudes GET son idempotentes y deben no cree, modifique o destruya 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 mejor seguridad. Rails no emite el mismo token almacenado con todos los formularios. 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

Utilizan 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 modificar los recursos del servidor.


EDIT: Consulta el comentario de @erturne con respecto a que las solicitudes GET sean idempotentes. Lo explica mejor que yo aquí.

contestado el 12 de mayo de 18 a las 11:05

@Faisal, ¿es posible entonces que un atacante simplemente lea / capture el elemento 'oculto' del formulario para el Servicio A y obtenga ese token único generado para el usuario, dado que ha obtenido acceso a la sesión iniciada por el usuario? para el servicio A? - marcamillion

@marcamillion: Si alguien secuestró su sesión en el servicio A, entonces el token de autenticidad no lo protegerá. El secuestrador podrá enviar una solicitud y se le permitirá continuar. - Faisal

@zabba: Rails genera una excepción ActionController :: InvalidAuthenticityToken si se envía un formulario sin el token adecuado. Puede rescatar_de la excepción y realizar el procesamiento que desee. - Faisal

re "También asegúrese de no realizar ninguna solicitud GET que pueda modificar los recursos del servidor". - esto incluye no usar match () en rutas que potencialmente podrían permitir solicitudes GET a acciones del controlador destinadas a recibir solo POST - Steven Soroka

"... y la solicitud debe ser idempotente (si ejecuta el mismo comando varias veces, debe obtener el mismo resultado cada vez)". Solo una sutil aclaración aquí. Seguro significa que no tiene efectos secundarios. Idempotent significa el mismo efecto secundario sin importar cuántas veces se llame a un servicio. Todos los servicios seguros son inherentemente idempotentes porque no tienen efectos secundarios. Llamar a GET en un recurso de tiempo actual varias veces devolvería un resultado diferente cada vez, pero es seguro (y por lo tanto idempotente). - erturne

El token de autenticidad está diseñado para que sepa que su formulario se envía desde su sitio web. Se genera a partir de 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 los rieles que le niegan 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 sobre esto en el documentación.

Respondido el 31 de enero de 11 a las 03:01

¿Qué es CSRF?

El token de autenticidad es una contramedida a 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, un anuncio patrocinado de una organización que no sea 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 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 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 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 que ocurrió el ataque.
  • Esto se denomina Falsificación de solicitudes entre sitios (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 el token adecuado.
  • Token de ejemplo: identificador de sesión cifrado con la clave secreta del servidor.
  • Rails genera automáticamente dichos tokens: vea el campo de entrada Authenticity_token en todos los formularios.

respondido 20 nov., 15:19

Aquí hay una versión de esta misma explicación que es menos precisa pero también menos abstracta: stackoverflow.com/a/33829607/2810305 - Lutz Prechelt

No estoy seguro, pero, ¿los navegadores modernos permiten enviar solicitudes no idempotentes (POST / PUT / DELETE) a otro dominio? Supongo que debe haber protección contra tales cosas en el propio navegador: dividir entre cero

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

CSRF

Suponga que 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 pirata informático podría simplemente enviar una solicitud HTTP al servidor diciendo GET /transfer?amount=$1000000&account-to=999999, ¿derecho?

enter image description here

Equivocado. El ataque de los piratas informáticos no funcionará. ¿El servidor básicamente pensará?

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

¿Cómo sabe esto el servidor? 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 su navegador. De esa manera, 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ó correctamente hace 2.5 minutos. Está listo para irse.

Un hacker podría pensar:

Mmm. Una solicitud HTTP normal no funcionará, pero si pudiera conseguirlo session_id galleta, estaría dorado.

El navegador del usuario tiene un montón de cookies configuradas para el bank.com dominio. Cada vez que el usuario realiza una solicitud al bank.com dominio, todas las cookies se envían. Incluyendo el session_id Galleta.

Entonces, si un hacker pudiera conseguir para realizar la solicitud GET que transfiere dinero a su cuenta, tendrá éxito. ¿Cómo pudo engañarte para que lo hicieras? Con falsificación de solicitud entre sitios.

En realidad, es bastante simple. El pirata informático podría hacer que visite 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 del usuario se encuentre 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 ha iniciado sesión recientemente en bank.com... la session_id Se establecerá una cookie y el servidor pensará que el usuario tenía la intención de transferir $ 1,000,000 a la cuenta 999999.

enter image description here

Bueno, simplemente no visite sitios peligrosos y estará bien.

Eso no es suficiente. ¿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 verdad. Un formulario que envía una solicitud POST se puede generar dinámicamente. Aquí está el ejemplo del Guía de rieles 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="/es/" 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 debe saber qué es este token? Se genera aleatoriamente un valor diferente cada vez que se genera el formulario:

enter image description here

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

Respondido 24 Jul 18, 00:07

Ejemplo de ataque mínimo que se evitaría: CSRF

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 cookies de sesión, las cookies se enviarán y la transferencia se realizará sin que usted lo sepa.

Ahí es donde entra en juego el token 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 pudiera haberlo adivinado ya que es un gran número aleatorio.

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

Política del mismo origen

Pero, ¿qué pasa si el atacante realiza dos solicitudes con JavaScript, una para leer el token y la segunda para realizar la transferencia?

¡El patrón del token del sincronizador por sí solo no es suficiente para evitarlo!

Aquí es donde la Política de Mismo Origen viene al rescate, como he explicado en: https://security.stackexchange.com/questions/8264/why-is-the-same-origin-policy-so-important/72569#72569

Cómo envía Rails los tokens

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

Básicamente:

  • Ayudantes HTML como form_tag agregue un campo oculto al formulario por usted si no es un formulario GET

  • AJAX se gestiona automáticamente por jquery-ujs, que lee el token 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 en caché obsoletos.

Otros enfoques de prevención

Respondido 02 ago 19, 10:08

Gracias, pero su punto de confiar en la misma política de origen para no poder leer el token CSRF primero parece erróneo. Entonces, primero dice que puede PUBLICAR en un origen diferente pero no puede leerlo, parece extraño, pero supongo que es correcto, pero podría inyectar una imagen o una etiqueta de secuencia de comandos con un acceso a la página y vincular un controlador para analizar la respuesta. y lo consigues si? - bjm88

@ bjm88 inyectar el script donde? ¿En su sitio o en el sitio atacado? Si se ataca el sitio, permitir la inyección de scripts es una falla de seguridad bien conocida y efectivamente empeña el sitio web. Cada sitio web debe combatirlo mediante el saneamiento de los insumos. Para las imágenes, no veo cómo se pueden usar para un ataque. En el sitio atacante: puedes modificar tu navegador para permitir la lectura y, por lo tanto, empeñarte automáticamente a voluntad :-) pero los navegadores decentes lo impiden de forma predeterminada, pruébalo. - Ciro Santilli TRUMP BAN ES MALO

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

En pocas palabras, 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 tiene acceso a una cookie creada. en el lado del cliente.

Respondido el 03 de junio de 09 a las 00:06

desde Authenticity Token es muy importante, y en Rails 3.0+ puedes usar

 <%= token_tag nil %>

crear

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

dondequiera

Respondido 01 ago 12, 09:08

Esto me ayudó. En realidad estaba tratando de hacer XSS en la página de inicio de sesión, no con fines nefastos, sino para crear una nueva sesión con un nombre de usuario precargado. Ahora sé que puedo usar value="token_value". - Michael

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 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/

Respondido 31 ago 11, 03:08

Métodos Donde authenticity_token Se requiere

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

Por qué es necesario

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

Respondido el 26 de enero de 16 a las 11:01

En realidad, ¿no es al revés? GET es idempotente ya que su llamada no debe alterar el estado del sistema, donde los verbos PUT POST y DELETE NO son verbos idempotentes ya que alteran el estado del sistema. IE: Authenticity_token es necesario en el caso de métodos NO idempotentes. - Jean-Théo

@ Jean-Daube, uma: idempotente significa que si se hace dos veces, la acción solo ocurre una vez. OBTENER, PONER y ELIMINAR son idempotente: w3.org/Protocols/rfc2616/rfc2616-sec9.html La propiedad clave aquí no es la idempotencia, sino si el método cambia o no los datos, que se llama "Método seguro" o no. - Ciro Santilli TRUMP BAN ES MALO

¿Qué es un authentication_token?

Esta es una cadena aleatoria utilizada por la aplicación rails para asegurarse de que el usuario solicita o realiza 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, se agrega automáticamente un authentication_token; de lo contrario, puede usar <%= csrf_meta_tag %>.

Respondido 04 Feb 17, 18:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.