Saltar al contenido principal




Reduzca la superficie de ataque DOM XSS de su aplicación.

Aparece en:
Seguro y a salvo

¿Por qué debería preocuparte?

La secuencia de comandos de sitios cruzados basada en DOM (DOM XSS) es una de las vulnerabilidades de seguridad web más comunes, y es muy fácil introducirla en su aplicación. Tipos de confianza
Brindarle las herramientas para escribir, revisar la seguridad y mantener aplicaciones libres de vulnerabilidades DOM XSS al hacer que las peligrosas funciones de la API web sean seguras de manera predeterminada. Los tipos de confianza son compatibles con Chrome 83 y polyfill está disponible para otros navegadores. Ver Compatibilidad del navegador para obtener información actualizada sobre compatibilidad con varios navegadores.

Término clave:
Las secuencias de comandos entre sitios basadas en DOM ocurren cuando los datos de un usuario controlan
fuente (como el nombre de usuario o la URL de redireccionamiento tomada del fragmento de URL) alcanza un lavabo, que es una función como eval() o un creador de propiedades como
.innerHTML, que puede ejecutar código JavaScript arbitrario.

Antecedentes

Durante muchos años DOM XSS
ha sido una de las vulnerabilidades de seguridad web más frecuentes y peligrosas.

Hay dos grupos distintos de secuencias de comandos entre sitios. Algunas vulnerabilidades XSS son causadas por el código del lado del servidor que crea de manera insegura el código HTML que forma el sitio web. Otros tienen una causa raíz en el cliente, donde el código JavaScript llama a funciones peligrosas con contenido controlado por el usuario.

A evitar XSS del lado del servidor, no genere HTML mediante la concatenación de cadenas y utilice bibliotecas de plantillas seguras con escape automático contextual. Usar una Política de seguridad de contenido basada en nonce para una mitigación adicional contra los errores que inevitablemente ocurren.

Ahora, un navegador también puede ayudar a prevenir los XSS del lado del cliente (también conocidos como basados ​​en DOM) con Tipos de confianza.

Introducción a la API

Los tipos de confianza funcionan bloqueando las siguientes funciones de sumidero de riesgo. Es posible que ya reconozca a algunos de ellos, como proveedores de navegadores y marcos web ya lo aleja del uso de estas funciones por razones de seguridad.

Los tipos de confianza requieren que procese los datos antes de pasarlos a las funciones de receptor anteriores. El solo uso de una cadena fallará, ya que el navegador no sabe si los datos son confiables:

No

anElement.innerHTML  = location.href;

Con Trusted Types habilitado, el navegador lanza un Error de tecleado y evita el uso de un fregadero DOM XSS con una cuerda.

Para indicar que los datos se procesaron de forma segura, cree un objeto especial: un tipo de confianza.

Hacer

anElement.innerHTML = aTrustedHTML;

Con los tipos de confianza habilitados, el navegador acepta un TrustedHTML objeto para receptores que esperan fragmentos de HTML. Tambien hay TrustedScript y TrustedScriptURL Objetos para otros lavabos sensibles.

Los tipos de confianza reducen considerablemente el DOM XSS superficie de ataque
de su aplicación. Simplifica las revisiones de seguridad y le permite hacer cumplir las verificaciones de seguridad basadas en tipos que se realizan al compilar, enlazar o empaquetar su código en tiempo de ejecución, en el navegador.

Cómo utilizar los tipos de confianza

Prepárese para los informes de infracción de la política de seguridad de contenido

Puede implementar un recopilador de informes (como el de código abierto go-csp-collector), o utilice uno de los equivalentes comerciales. También puede depurar las infracciones en el navegador:

window.addEventListener('securitypolicyviolation',
console.error.bind(console));

Agregue el siguiente encabezado de respuesta HTTP a los documentos que desea migrar a tipos de confianza.

Content-Security-Policy-Report-Only: require-trusted-types-for 'script'; report-uri //my-csp-endpoint.example

Ahora todas las violaciones se informan a //my-csp-endpoint.example, pero el sitio web sigue funcionando. La siguiente sección explica cómo //my-csp-endpoint.example trabajos.

Precaución:
Los tipos de confianza solo están disponibles en contexto seguro
como HTTPS y localhost.

Identificar infracciones de tipos de confianza

A partir de ahora, cada vez que Trusted Types detecte una infracción, se enviará un informe a un report-uri. Por ejemplo, cuando su aplicación pasa una cadena a innerHTML, el navegador envía el siguiente informe:

{
"csp-report": {
"document-uri": "https://my.url.example",
"violated-directive": "require-trusted-types-for",
"disposition": "report",
"blocked-uri": "trusted-types-sink",
"line-number": 39,
"column-number": 12,
"source-file": "https://my.url.example/script.js",
"status-code": 0,
"script-sample": "Element innerHTML <img src=x"
}
}

Esto dice que en https://my.url.example/script.js en la línea 39 innerHTML fue llamado con la cadena que comienza con <img src=x. Esta información debería ayudarlo a delimitar qué partes del código pueden estar introduciendo DOM XSS y deben cambiar.

La mayoría de las violaciones como esta también se pueden detectar ejecutando un linter de código o verificadores de código estático
en su base de código. Esto ayuda a identificar rápidamente una gran cantidad de infracciones.

Dicho esto, también debe analizar las infracciones de CSP, ya que se activan cuando se ejecuta el código no conforme.

Arregle las infracciones

Hay un par de opciones para corregir una infracción de tipo de confianza. Puede eliminar el código infractor, utilizar una biblioteca, crear una política de tipo de confianza o, como último recurso, crear una política predeterminada.

Reescribe el código ofensivo

¿Quizás la funcionalidad no conforme ya no sea necesaria o se pueda reescribir de una manera moderna sin usar las funciones propensas a errores?

No

el.innerHTML = '<img src=xyz.jpg>';

Hacer

el.textContent = '';
const img = document.createElement('img');
img.src = 'xyz.jpg';
el.appendChild(img);

Usa una biblioteca

Algunas bibliotecas ya generan tipos de confianza que puede pasar a las funciones de receptor. Por ejemplo, puede utilizar
DOMPurify para desinfectar un fragmento de HTML, eliminando las cargas útiles XSS.

import DOMPurify from 'dompurify';
el.innerHTML = DOMPurify.sanitize(html, {RETURN_TRUSTED_TYPE: true);

DOMPurify admite tipos de confianza y devolverá HTML desinfectado envuelto en un TrustedHTML objeto de modo que el navegador no genere una infracción.

Precaución:
Si la lógica de desinfección en DOMPurify tiene errores, es posible que su aplicación aún tenga una vulnerabilidad DOM XSS. Los tipos de confianza te obligan a procesar un valor de algun modo, pero aún no defina cuáles son las reglas de procesamiento exactas y si son seguras.

Cree una política de tipo de confianza

A veces no es posible eliminar la funcionalidad y no existe una biblioteca para desinfectar el valor y crear un Tipo de confianza para usted. En esos casos, cree usted mismo un objeto Trusted Type.

Para eso, primero crea un política. Las políticas son fábricas de tipos de confianza que imponen ciertas reglas de seguridad en su entrada:

if (window.trustedTypes && trustedTypes.createPolicy) { 
const escapeHTMLPolicy = trustedTypes.createPolicy('myEscapePolicy', {
createHTML: string => string.replace(/</g, '&lt;')
});
}

Este código crea una política llamada myEscapePolicy que puede producir TrustedHTML
objetos a través de su createHTML() función. Las reglas definidas escaparán HTML < caracteres para evitar la creación de nuevos elementos HTML.

Utilice la política así:

const escaped = escapeHTMLPolicy.createHTML('<img src=x onerror=alert(1)>');
console.log(escaped instanceof TrustedHTML);
el.innerHTML = escaped;

Mientras que la función de JavaScript pasó a trustedTypes.createPolicy() como
createHTML() devuelve una cadena, createPolicy() devuelve un objeto de política que envuelve el valor de retorno en un tipo correcto, en este caso TrustedHTML.

Utilice una política predeterminada

A veces no se puede cambiar el código ofensivo. Por ejemplo, este es el caso si está cargando una biblioteca de terceros desde una CDN. En ese caso, utilice un
política predeterminada:

if (window.trustedTypes && trustedTypes.createPolicy) { 
trustedTypes.createPolicy('default', {
createHTML: (string, sink) => DOMPurify.sanitize(string, {RETURN_TRUSTED_TYPE: true});
});
}

La póliza con nombre default se usa siempre que se usa una cadena en un receptor que solo acepta Trusted Type.

Gotchas!

Use la política predeterminada con moderación y prefiera refactorizar la aplicación para usar políticas regulares en su lugar. Al hacerlo, se fomentan los diseños en los que las reglas de seguridad están cerca de los datos que procesan, donde tiene el mayor contexto para desinfectar correctamente el valor.

Cambiar para hacer cumplir la Política de seguridad del contenido

Cuando su aplicación ya no produzca infracciones, puede comenzar a hacer cumplir los tipos de confianza:

Content-Security-Policy: require-trusted-types-for 'script'; report-uri //my-csp-endpoint.example

¡Voila! Ahora, no importa cuán compleja sea su aplicación web, lo único que puede introducir una vulnerabilidad DOM XSS es el código en una de sus políticas, y puede bloquearlo aún más si limitar la creación de políticas.

Otras lecturas

R Marketing Digital