Asegúrate de que la CSP sea eficaz contra los ataques XSS

Una Política de Seguridad del Contenido (CSP) ayuda a garantizar que el propietario del sitio confíe en el contenido que se carga en la página. Los CSP mitigan los ataques de secuencias de comandos entre sitios (XSS) porque pueden bloquear las secuencias de comandos no seguras que inyectan los atacantes. Sin embargo, el CSP se puede eludir fácilmente si no es lo suficientemente estricto. Consulta Cómo mitigar la escritura de secuencias de comandos entre sitios (XSS) con una Política de Seguridad del Contenido (CSP) estricta para obtener más información. Lighthouse recopila los CSP aplicados en el documento principal y, si se pueden omitir, informa los problemas del evaluador de CSP.

Informe de Lighthouse que advierte que no se encontró ninguna CSP en el modo de aplicación forzosa.
Advertencia del informe de Lighthouse que indica que no se encontró ninguna CSP en el modo de aplicación forzosa.

Prácticas obligatorias para un CSP que no se pueda omitir

Implementa las siguientes prácticas para asegurarte de que no se pueda omitir tu CSP. Si se puede omitir el CSP, Lighthouse emitirá una advertencia de gravedad alta.

XSS de destino del CSP

Para atacar XSS, un CSP debe incluir las directivas script-src, object-src y base-uri. El CSP también debe estar libre de errores de sintaxis.

script-src y object-src protegen una página de secuencias de comandos y complementos no seguros, respectivamente. Como alternativa, se puede usar default-src para configurar una política amplia en lugar de muchas directivas, incluidas script-src y object-src.

base-uri evita la inserción de etiquetas <base> no autorizadas que se pueden usar para redireccionar todas las URLs relativas (como secuencias de comandos) a un dominio controlado por un atacante.

La CSP usa nonces o hashes para evitar eludir la lista de entidades permitidas.

Un CSP que configura una lista de entidades permitidas para script-src se basa en la suposición de que todas las respuestas que provienen de un dominio de confianza son seguras y se pueden ejecutar como secuencias de comandos. Sin embargo, esta suposición no se aplica a las aplicaciones modernas. Algunos patrones comunes y benignos, como exponer interfaces JSONP y alquilar copias de la biblioteca de AngularJS, permiten que los atacantes escapen de los límites de CSP.

En la práctica, si bien es posible que no sea evidente para los autores de aplicaciones, un atacante con un error de XSS puede eludir la mayoría de las listas de entidades permitidas de script-src y proporcionar poca protección contra la inserción de secuencias de comandos. En cambio, los enfoques basados en nonce y hash no tienen estos problemas y facilitan la adopción y el mantenimiento de una política más segura.

Por ejemplo, este código usa un extremo JSONP alojado en un dominio de confianza para insertar una secuencia de comandos controlada por un atacante:

CSP:

script-src https://trusted.example.com

HTML:

<script src="https://trusted.example.com/path/jsonp?callback=alert(document.domain)//"></script>

Para evitar que se eludan, una CSP debe permitir secuencias de comandos de forma individual con nonces o hashes y usar "estricto-dinámico" en lugar de una lista de entidades permitidas.

Recomendaciones adicionales para un CSP seguro

Implementa las siguientes prácticas para obtener más seguridad y compatibilidad. Si el CSP no sigue una de las recomendaciones, Lighthouse emitirá una advertencia de gravedad media.

Configura los informes de CSP

Configurar un destino de informes te ayudará a supervisar si hay interrupciones. Puedes configurar el destino de los informes con las directivas report-uri o report-to. Actualmente, no todos los navegadores modernos admiten report-to, por lo que se recomienda usar ambos o solo report-uri.

Si algún contenido incumple el CSP, el navegador enviará un informe al destino configurado. Asegúrate de tener una aplicación configurada en este destino que controle estos informes.

Define la CSP en un encabezado HTTP

Una CSP se puede definir en una metaetiqueta de la siguiente manera:

<meta http-equiv="Content-Security-Policy" content="script-src 'none'">

Sin embargo, si es posible, debes definir una CSP en un encabezado de respuesta HTTP. Una inserción antes de la metaetiqueta omitirá el CSP. Además, frame-ancestors, sandbox y los informes no son compatibles con los CSP de metaetiquetas.

Asegúrate de que la CSP sea retrocompatible

No todos los navegadores admiten nonces o hashes de CSP, por lo que se recomienda agregar unsafe-inline como resguardo para los navegadores que no cumplen con los requisitos. Si el navegador admite nonces o hashes, se ignorará unsafe-inline.

Del mismo modo, no todos los navegadores son compatibles con strict-dynamic. Se recomienda establecer una lista de entidades permitidas como resguardo para los navegadores que no cumplan con los requisitos. La lista de entidades permitidas se ignorará en los navegadores que admitan strict-dynamic.

Cómo desarrollar un CSP estricto

A continuación, se muestra un ejemplo del uso de un CSP estricto con una política basada en un nonce.

CSP:

script-src 'nonce-random123' 'strict-dynamic' 'unsafe-inline' https:;
object-src 'none';
base-uri 'none';
report-uri https://reporting.example.com;

HTML:

<script nonce="random123" src="https://trusted.example.com/trusted_script.js"></script>

random123 sería cualquier cadena base64 generada del servidor cada vez que se carga la página. unsafe-inline y https: se ignoran en los navegadores modernos debido al nonce y strict-dynamic. Para obtener más información sobre cómo adoptar un CSP estricto, consulta la Guía de CSP estricto.

Puedes verificar un CSP en busca de posibles bypasses con Lighthouse y el evaluador de CSP. Si deseas probar un CSP nuevo sin correr el riesgo de dañar las páginas existentes, define el CSP en modo de solo informes con Content-Security-Policy-Report-Only como el nombre del encabezado. Esta acción enviará incumplimientos del CSP a los destinos de informes que hayas configurado con report-to y report-uri, pero no aplicará el CSP.