El token XSRF se adjunta a las formas dinámicamente

2

No he visto esto en ningún lugar en la naturaleza, por lo que me pregunto si es seguro inyectar en formas del mismo origen la entrada oculta que contiene el token XSRF utilizando JavaScript como este:

document.addEventListener('DOMContentLoaded', () => {
    // Get token from <html> tag
    const XSRF_TOKEN = document.documentElement.getAttribute('data-xsrf-token');
    const uri = new URI(document.URL);

    // Loop through all forms
    Array.from(document.getElementsByTagName('form')).forEach(el => {
        let actionUri = new URI(el);

        // Only append hidden input to same-origin forms with method POST
        if (actionUri.origin() === uri.origin() && el.method === 'post') {
            let tokenInput = document.createElement('input');
            tokenInput.name = 'xsrf_token';
            tokenInput.type = 'hidden';
            tokenInput.value = XSRF_TOKEN;
            el.appendChild(tokenInput);
        }
    })
});

El token se generaría por usuario por sesión y se entregaría con la página HTML como un valor de atributo en el elemento <html> .

Por supuesto, esto solo funcionaría en las partes de la aplicación para las que requerimos JavaScript. Es mucho más fácil que poner la entrada oculta en todas partes.

Muchos sitios sugieren usar un marco para esto, sin embargo, esta no es una opción factible y si deben ser entradas ocultas en la carga de la página, lo mejor que puedo hacer es crear una función Twig auxiliar para generar la etiqueta, pero eso aún requiere que rociado por todas partes. Y si este es el caso, ¿cómo funcionan los formularios creados dinámicamente?

No creo que el método JavaScript sea menos seguro que <input type=hidden> en todas partes porque el token es recuperable del formulario en caso de XSS, pero ¿hay algo más que me esté faltando?

    
pregunta rink.attendant.6 12.01.2017 - 01:57
fuente

1 respuesta

0

Los tokens CSRF inyectados dinámicamente son un enfoque probado en el campo sin fallas de seguridad inherentes.

Por ejemplo, el proyecto OWASP CSRFGuard admite esta función:

  

OWASP CSRFGuard 3 admite la capacidad de inyectar de forma dinámica tokens de prevención CSRF en todo el DOM cargado actualmente en el navegador del usuario. Esta estrategia es extremadamente valiosa en lo que respecta al rendimiento del lado del servidor, ya que simplemente requiere la entrega de un archivo JavaScript dinámico.

El blog de tecnología iFixit también tiene un artículo sobre su propia implementación "minimalista" de esa idea:

  

Usamos una pequeña cantidad de javascript para establecer automáticamente una cookie y agregar un campo de formulario inmediatamente antes de enviar el formulario. El servidor luego compara el campo de formulario con la cookie e ignora la solicitud si no coinciden. Esto nos libera de la molestia de asegurar que cada formulario incluya un csrf <input> oculto en cada plantilla.

En su ejemplo de código puede ver que el token se agrega justo antes del envío, lo que probablemente sea más seguro que agregarlo carga de documentos (ya que algo podría hacer que el destino del formulario cambie mientras tanto):

window.addEvent('domready', function() {
   /**
    * Setup triggers on the .submit() function and the 'submit' event so we
    * can add csrf inputs immediately before the form is submitted.
    */
   $$('form').each(function(form) {
      // Ensure all forms submitted via a traditional 'submit' button have
      // an up-to-date CSRF input
      form.addEvent('submit', function() {
         ensureFormHasCSRFFormField(form);
      });
      // Ensure all forms submitted via form.submit() have an up-to-date CSRF
      // input
      var oldSubmit = form.submit;
      // Wrap the default submit() function with our own
      form.submit = function () {
         ensureFormHasCSRFFormField(form);
         return oldSubmit.apply(form, Array.from(arguments));
      }
   });
});

No hay problemas de seguridad inherentes con este enfoque, siempre y cuando se asegure de que el destino del formulario tenga el origen correcto. Incluso mitiga algunos ataques, por ejemplo. en este escenario . (El artículo trata sobre un defecto XSS en el que el CSP evita todos los scripts en línea, por lo que el atacante se limita a la inyección de HTML puro. El autor presenta un método para cambiar el objetivo de la acción de formulario sin ningún JS con el fin de exfiltrar un CSRF token establecido en un campo de entrada oculto. Ahora, si ese token se hubiera agregado dinámicamente, el ataque habría fallado porque su script reconocería que el formulario se envía a un origen no confiable.)

    
respondido por el Arminius 12.01.2017 - 02:54
fuente

Lea otras preguntas en las etiquetas