Mitiga ataques XSS con Content Security Policy

:bookmark: Esta guía explica cómo utilizar la Política de Seguridad de Contenido (CSP) para mitigar los ataques de Cross-Site Scripting (XSS) en Discourse. Cubre los conceptos básicos de CSP, su configuración y las mejores prácticas.

:person_raising_hand: Nivel de usuario requerido: Administrador

Resumen

La Política de Seguridad de Contenido (CSP) es una función de seguridad crucial en Discourse que ayuda a proteger contra ataques de Cross-Site Scripting (XSS) y otras inyecciones. Esta guía cubre los fundamentos de CSP, cómo se implementa en Discourse y cómo configurarla para tu sitio.

¿Qué es la Política de Seguridad de Contenido?

La Política de Seguridad de Contenido es una capa adicional de seguridad que ayuda a detectar y mitigar ciertos tipos de ataques, incluidos los ataques de Cross-Site Scripting (XSS) y las inyecciones de datos. CSP funciona especificando qué fuentes de contenido se consideran de confianza e instruyendo al navegador para que solo ejecute o renderice recursos desde esas fuentes confiables.

El XSS sigue siendo una de las vulnerabilidades web más comunes. Al implementar CSP, Discourse permite que solo los scripts de fuentes confiables se carguen y ejecuten, reduciendo significativamente el riesgo de ataques XSS.

Implementación de CSP en Discourse

A partir de la versión 3.3.0.beta1 de Discourse, esta plataforma implementa una CSP de ‘strict-dynamic’. Este enfoque utiliza un único valor nonce- y la palabra clave strict-dynamic en la directiva script-src. Todas las etiquetas \u003cscript\u003e iniciales en el núcleo y los temas reciben automáticamente el atributo nonce= apropiado.

La política predeterminada incluye las siguientes directivas:

  • script-src: Especifica las fuentes válidas para JavaScript.
  • worker-src: Especifica las fuentes válidas para los scripts de ServiceWorker.
  • object-src: Bloquea la ejecución de plugins (Flash, Java, etc.).
  • base-uri: Restringe las URL para los elementos \u003cbase\u003e.
  • manifest-src: Restringe las URL para los manifiestos de aplicaciones web.
  • frame-ancestors: Controla qué sitios pueden incrustar tu instancia de Discourse en un iframe.
  • upgrade-insecure-requests: Actualiza automáticamente las solicitudes HTTP a HTTPS (incluido cuando force_https está habilitado).

Configuración de CSP en Discourse

Configuraciones disponibles

  • content_security_policy: Habilita o deshabilita CSP (predeterminado: on).
  • content_security_policy_report_only: Habilita el modo CSP Report-Only (predeterminado: off).
  • content_security_policy_script_src: Te permite extender la directiva script-src predeterminada.
  • content_security_policy_frame_ancestors: Habilita la directiva frame_ancestors (predeterminado: on).

Cómo habilitar CSP

  1. Navega a tu panel de Administración.
  2. Ve a la configuración de Seguridad.
  3. Busca la configuración content_security_policy y asegúrate de que esté habilitada.

Se recomienda comenzar con el modo CSP Report-Only para identificar posibles problemas antes de habilitar CSP completamente:

  1. Habilita la configuración content_security_policy_report_only.
  2. Monitorea la consola de tu navegador en busca de violaciones de CSP.
  3. Aborda cualquier violación legítima extendiendo la CSP según sea necesario.
  4. Una vez que estés seguro de que no hay falsos positivos, deshabilita el modo Report-Only y habilita CSP completamente.

Extender la CSP predeterminada

Si necesitas permitir fuentes de scripts adicionales, puedes extender la directiva script-src utilizando la configuración content_security_policy_script_src. Puedes agregar:

  • Fuentes basadas en hash.
  • 'wasm-unsafe-eval'.
  • 'unsafe-eval' (úsalo con precaución).

Por ejemplo:

'sha256-QFlnYO2Ll+rgFRKkUmtyRublBc7KFNsbzF7BzoCqjgA=' 'unsafe-eval'

:warning: Ten cuidado al agregar 'unsafe-eval' u otras directivas permisivas, ya que pueden reducir la efectividad de CSP.

CSP e integraciones de terceros

Al utilizar servicios de terceros como Google Tag Manager, Google Analytics o servicios de publicidad, es posible que debas ajustar tu configuración de CSP. En la mayoría de los casos con Discourse versión 3.3.0.beta1 o posterior, los scripts externos deberían funcionar sin configuración adicional debido a la implementación de CSP de ‘strict-dynamic’.

Si encuentras problemas, es posible que debas:

  1. Identificar las fuentes de scripts necesarias monitoreando la consola de tu navegador.
  2. Agregar las fuentes necesarias a la configuración content_security_policy_script_src.
  3. Para integraciones complejas como servicios de publicidad que cargan recursos externos, es posible que debas habilitar la renderización entre dominios (Ejemplo de PR de discourse-adplugin que hace esto).

Mejores prácticas

  1. Comienza con el modo CSP Report-Only para identificar posibles problemas.
  2. Ajusta progresivamente tu CSP a medida que resuelves las violaciones legítimas.
  3. Revisa regularmente tu configuración de CSP y ajústala según sea necesario.
  4. Ten cuidado al agregar directivas permisivas como 'unsafe-eval' o 'wasm-unsafe-eval'.
  5. Mantén tu instancia de Discourse actualizada para beneficiarte de las últimas mejoras de CSP.

Preguntas frecuentes

P: Estoy viendo muchos informes de violaciones de CSP. ¿Debería preocuparme?
R: Muchas violaciones de CSP son falsos positivos, a menudo causados por extensiones del navegador u otros scripts no relacionados. Concéntrate en abordar las violaciones relacionadas con la funcionalidad de tu sitio.

P: ¿Puedo usar CSP con Google AdSense u otras redes publicitarias?
R: Sí, pero es posible que debas usar configuraciones de CSP más permisivas. Comienza con el modo Report-Only y ajusta tu configuración en función de las violaciones reportadas.

P: ¿Cómo soluciono problemas de CSP?
R: Utiliza las herramientas de desarrollador de tu navegador para monitorear la consola en busca de mensajes de violación de CSP. Estos te ayudarán a identificar qué recursos están siendo bloqueados y por qué.

Recursos adicionales

56 Me gusta
Adsense Not Working after Recent Discourse Update
Discourse 2.2.0.beta6 Release Notes
Adding statcounter code
How to restart Discourse after server reboot?
How to install npm packages in custom themes/plugins
Interactive SVG using <object>?
Video Upload to YouTube and Vimeo using Theme Component
Embed HTML5 player for MP3 file
2.5.0.beta5 breaks retort plugin
Should I load third-party libraries from vendor or cdn?
Word Cloud plugin
Embed widget within text in a topic
Discourse Intercom (Advanced)
"Unsafe JavaScript attempt to initiate navigation"
Google Tag Manager and Discourse CSP (Content Security Policy)
Cookie Consent, GDPR, and Discourse
A strange question about google ad display in my site
How to pass a component setting as a value to an attribute?
Need help integrating code wrote on Edittext to the Discourse
Issue with Activate Account Page After Update to 3.4.0 (Blank Page)
Any approved method for adding Javascript before body close?
(Superseded) Experimenting with a 'strict-dynamic' Content Security Policy (CSP)
Can't get script tag to work in landing pages plugin due to content-security-policy
How to embed Razorpay subscription button with CSP restrictions
Push custom events to Google Tag Manager and Analytics
Can I add a snippet to the header?
JS script is not loading
How do we fire scripts after topic HTML is rendered in DOM?
Iframe issue without URL
Where to place ad script?
We couldn't find the code on your site
Javascript not working in customised areas
Difficulties in correctly adding external JavaScript
Report Only CSP Violations
Nginx config in Discourse Docker?
EPN Smart Links
Discourse 2.2.0.beta9 Release Notes
"Refused to load the script" when adding adsense
Why Cookie Consent Doesn't Show Up?
[DigitalOcean] hostname having "www" in A records showing blank page
[DigitalOcean] hostname having "www" in A records showing blank page
Communities with embedded Twitter Feeds
How to add analytics and pixel scripts avoiding Content Security Policy (XSS)
When install html script facing issue?
Discourse 2.4.0.beta10 Release Notes
Add CSP sources to the plugin
IP does not redirect to domain, domain shows white page
DISCOURSE_CDN_URL causes content security policy violations?
Header content is missing due to CSP
How to insert something right after <head>?
How can I embed tracking JS into Discourse
How do I integrate ? cookiebot.com in meinen Forum?
Adding Cookie Consent Banner
Confused about remotely loaded javascript content
User input validation
Custom JS script in theme component not loading