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

Una Política de Seguridad del Contenido (CSP) ayuda a garantizar que cualquier contenido cargado en la página sea de confianza para el propietario del sitio. Los CSP mitigan los ataques de secuencias de comandos entre sitios (XSS) porque pueden bloquear secuencias de comandos no seguras que inserten los atacantes. Sin embargo, la CSP se puede omitir fácilmente si no es lo suficientemente estricta. Para obtener más información, consulta Mitigación de las secuencias de comandos entre sitios (XSS) con una Política de Seguridad del Contenido (CSP) estricta. Lighthouse recopila las CSP aplicadas en el documento principal y, si se pueden eludir, informa los problemas a CSP Evaluator.

Un informe de Lighthouse advierte que no se encuentra ninguna CSP en el modo de aplicación forzosa.
Un informe de Lighthouse advierte que no se encontró ninguna CSP en el modo de aplicación forzosa.

Prácticas obligatorias para una CSP que no se puede omitir

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

La CSP se orienta a XSS

Para orientarse a XSS, una CSP debe incluir las directivas script-src, object-src y base-uri. La CSP tampoco debe tener errores de sintaxis.

script-src y object-src protegen una página contra secuencias de comandos no seguras y complementos no seguros, respectivamente. Como alternativa, se puede usar default-src para configurar una política amplia en lugar de varias 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 atacantes.

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

Una CSP que configura una lista de entidades permitidas para script-src se basa en la suposición de que todas las respuestas provenientes de un dominio de confianza son seguras y se pueden ejecutar como secuencias de comandos. Sin embargo, esta suposición no es válida para las aplicaciones modernas. Algunos patrones benignos comunes, como la exposición de interfaces JSONP y el aloje de copias de la biblioteca AngularJS, permiten a los atacantes escapar de los límites de CSP.

En la práctica, si bien puede que no sea evidente para los autores de las aplicaciones, un atacante con un error XSS puede eludir la mayoría de las listas de entidades permitidas de script-src, lo que proporciona poca protección contra la inserción de secuencias de comandos. Por el contrario, los enfoques basados en nonce y en 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 de JSONP alojado en un dominio de confianza para insertar una secuencia de comandos controlada por el atacante:

CSP:

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

HTML:

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

Para evitar la omisión, una CSP debe permitir las secuencias de comandos de forma individual que usen nonces o hashes, y usar "strict-dynamic" en lugar de una lista de entidades permitidas.

Recomendaciones adicionales para una CSP segura

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

Configura los informes de CSP

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

Si algún contenido infringe la 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 como la siguiente:

<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 inyección antes de la metaetiqueta omitirá la CSP. Además, frame-ancestors, sandbox y los informes no son compatibles con las CSP de metaetiquetas.

Asegúrate de que la CSP sea retrocompatible

No todos los navegadores admiten nonces y hashes de la CSP, por lo que se recomienda agregar unsafe-inline como resguardo para navegadores que no cumplan con las políticas. Si el navegador es compatible con nonces y hashes, se ignorará unsafe-inline.

Del mismo modo, strict-dynamic no es compatible con todos los navegadores. Se recomienda establecer una lista de entidades permitidas como resguardo para cualquier navegador que no cumpla con las políticas. Se ignorará la lista de entidades permitidas en los navegadores compatibles con strict-dynamic.

Cómo desarrollar una CSP estricta

A continuación, se muestra un ejemplo del uso de una CSP estricta con una política basada en 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 string base64 generada del servidor cada vez que se cargue la página. unsafe-inline y https: se ignoran en los navegadores modernos debido al nonce y a strict-dynamic. Para obtener más información sobre la adopción de una CSP estricta, consulta la Guía de CSP estrictas.

Puedes verificar una CSP para detectar posibles omisiones con Lighthouse y CSP Evaluator. Si deseas probar una CSP nueva sin correr el riesgo de generar errores en las páginas existentes, define la CSP en modo de solo informes con Content-Security-Policy-Report-Only como nombre del encabezado. Esta acción enviará los incumplimientos de CSP a cualquier destino de informes que hayas configurado con report-to y report-uri, pero no aplicará la CSP de manera forzosa.